Commit 95a34047 authored by David Fernandez's avatar David Fernandez

Merge branch 'system-note-and-events-on-issue-create' into 'master'

Fix missing system notes and system events on create issue [RUN ALL RSPEC] [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!61746
parents d52986a9 25b6738c
...@@ -184,7 +184,7 @@ class IssuableBaseService < ::BaseProjectService ...@@ -184,7 +184,7 @@ class IssuableBaseService < ::BaseProjectService
params[:assignee_ids] = process_assignee_ids(params, extra_assignee_ids: issuable.assignee_ids.to_a) params[:assignee_ids] = process_assignee_ids(params, extra_assignee_ids: issuable.assignee_ids.to_a)
end end
issuable.assign_attributes(params) issuable.assign_attributes(allowed_create_params(params))
before_create(issuable) before_create(issuable)
...@@ -194,6 +194,7 @@ class IssuableBaseService < ::BaseProjectService ...@@ -194,6 +194,7 @@ class IssuableBaseService < ::BaseProjectService
if issuable_saved if issuable_saved
create_system_notes(issuable, is_update: false) unless skip_system_notes create_system_notes(issuable, is_update: false) unless skip_system_notes
handle_changes(issuable, { params: params })
after_create(issuable) after_create(issuable)
execute_hooks(issuable) execute_hooks(issuable)
...@@ -233,7 +234,7 @@ class IssuableBaseService < ::BaseProjectService ...@@ -233,7 +234,7 @@ class IssuableBaseService < ::BaseProjectService
assign_requested_assignees(issuable) assign_requested_assignees(issuable)
if issuable.changed? || params.present? if issuable.changed? || params.present?
issuable.assign_attributes(params) issuable.assign_attributes(allowed_update_params(params))
if has_title_or_description_changed?(issuable) if has_title_or_description_changed?(issuable)
issuable.assign_attributes(last_edited_at: Time.current, last_edited_by: current_user) issuable.assign_attributes(last_edited_at: Time.current, last_edited_by: current_user)
...@@ -260,7 +261,7 @@ class IssuableBaseService < ::BaseProjectService ...@@ -260,7 +261,7 @@ class IssuableBaseService < ::BaseProjectService
issuable, old_labels: old_associations[:labels], old_milestone: old_associations[:milestone] issuable, old_labels: old_associations[:labels], old_milestone: old_associations[:milestone]
) )
handle_changes(issuable, old_associations: old_associations) handle_changes(issuable, old_associations: old_associations, params: params)
new_assignees = issuable.assignees.to_a new_assignees = issuable.assignees.to_a
affected_assignees = (old_associations[:assignees] + new_assignees) - (old_associations[:assignees] & new_assignees) affected_assignees = (old_associations[:assignees] + new_assignees) - (old_associations[:assignees] & new_assignees)
...@@ -505,6 +506,14 @@ class IssuableBaseService < ::BaseProjectService ...@@ -505,6 +506,14 @@ class IssuableBaseService < ::BaseProjectService
def update_timestamp?(issuable) def update_timestamp?(issuable)
issuable.changes.keys != ["relative_position"] issuable.changes.keys != ["relative_position"]
end end
def allowed_create_params(params)
params
end
def allowed_update_params(params)
params
end
end end
IssuableBaseService.prepend_mod_with('IssuableBaseService') IssuableBaseService.prepend_mod_with('IssuableBaseService')
...@@ -40,6 +40,20 @@ module Issues ...@@ -40,6 +40,20 @@ module Issues
super super
end end
def handle_changes(issue, options)
super
old_associations = options.fetch(:old_associations, {})
old_assignees = old_associations.fetch(:assignees, [])
handle_assignee_changes(issue, old_assignees)
end
def handle_assignee_changes(issue, old_assignees)
return if issue.assignees == old_assignees
create_assignee_note(issue, old_assignees)
end
def resolve_discussions_with_issue(issue) def resolve_discussions_with_issue(issue)
return if discussions_to_resolve.empty? return if discussions_to_resolve.empty?
......
...@@ -43,6 +43,7 @@ module Issues ...@@ -43,6 +43,7 @@ module Issues
end end
def handle_changes(issue, options) def handle_changes(issue, options)
super
old_associations = options.fetch(:old_associations, {}) old_associations = options.fetch(:old_associations, {})
old_labels = old_associations.fetch(:labels, []) old_labels = old_associations.fetch(:labels, [])
old_mentioned_users = old_associations.fetch(:mentioned_users, []) old_mentioned_users = old_associations.fetch(:mentioned_users, [])
......
...@@ -27,6 +27,33 @@ module MergeRequests ...@@ -27,6 +27,33 @@ module MergeRequests
enqueue_jira_connect_messages_for(merge_request) enqueue_jira_connect_messages_for(merge_request)
end end
def handle_changes(merge_request, options)
old_associations = options.fetch(:old_associations, {})
old_assignees = old_associations.fetch(:assignees, [])
old_reviewers = old_associations.fetch(:reviewers, [])
handle_assignees_change(merge_request, old_assignees) if merge_request.assignees != old_assignees
handle_reviewers_change(merge_request, old_reviewers) if merge_request.reviewers != old_reviewers
end
def handle_assignees_change(merge_request, old_assignees)
MergeRequests::HandleAssigneesChangeService
.new(project: project, current_user: current_user)
.async_execute(merge_request, old_assignees)
end
def handle_reviewers_change(merge_request, old_reviewers)
affected_reviewers = (old_reviewers + merge_request.reviewers) - (old_reviewers & merge_request.reviewers)
create_reviewer_note(merge_request, old_reviewers)
notification_service.async.changed_reviewer_of_merge_request(merge_request, current_user, old_reviewers)
todo_service.reassigned_reviewable(merge_request, current_user, old_reviewers)
invalidate_cache_counts(merge_request, users: affected_reviewers.compact)
new_reviewers = merge_request.reviewers - old_reviewers
merge_request_activity_counter.track_users_review_requested(users: new_reviewers)
merge_request_activity_counter.track_reviewers_changed_action(user: current_user)
end
def cleanup_environments(merge_request) def cleanup_environments(merge_request)
Ci::StopEnvironmentsService.new(merge_request.source_project, current_user) Ci::StopEnvironmentsService.new(merge_request.source_project, current_user)
.execute_for_merge_request(merge_request) .execute_for_merge_request(merge_request)
......
...@@ -15,6 +15,7 @@ module MergeRequests ...@@ -15,6 +15,7 @@ module MergeRequests
end end
def handle_changes(merge_request, options) def handle_changes(merge_request, options)
super
old_associations = options.fetch(:old_associations, {}) old_associations = options.fetch(:old_associations, {})
old_labels = old_associations.fetch(:labels, []) old_labels = old_associations.fetch(:labels, [])
old_mentioned_users = old_associations.fetch(:mentioned_users, []) old_mentioned_users = old_associations.fetch(:mentioned_users, [])
...@@ -31,8 +32,6 @@ module MergeRequests ...@@ -31,8 +32,6 @@ module MergeRequests
end end
handle_target_branch_change(merge_request) handle_target_branch_change(merge_request)
handle_assignees_change(merge_request, old_assignees) if merge_request.assignees != old_assignees
handle_reviewers_change(merge_request, old_reviewers) if merge_request.reviewers != old_reviewers
handle_milestone_change(merge_request) handle_milestone_change(merge_request)
handle_draft_status_change(merge_request, changed_fields) handle_draft_status_change(merge_request, changed_fields)
...@@ -220,24 +219,6 @@ module MergeRequests ...@@ -220,24 +219,6 @@ module MergeRequests
end end
end end
def handle_assignees_change(merge_request, old_assignees)
MergeRequests::HandleAssigneesChangeService
.new(project: project, current_user: current_user)
.async_execute(merge_request, old_assignees)
end
def handle_reviewers_change(merge_request, old_reviewers)
affected_reviewers = (old_reviewers + merge_request.reviewers) - (old_reviewers & merge_request.reviewers)
create_reviewer_note(merge_request, old_reviewers)
notification_service.async.changed_reviewer_of_merge_request(merge_request, current_user, old_reviewers)
todo_service.reassigned_reviewable(merge_request, current_user, old_reviewers)
invalidate_cache_counts(merge_request, users: affected_reviewers.compact)
new_reviewers = merge_request.reviewers - old_reviewers
merge_request_activity_counter.track_users_review_requested(users: new_reviewers)
merge_request_activity_counter.track_reviewers_changed_action(user: current_user)
end
def create_branch_change_note(issuable, branch_type, event_type, old_branch, new_branch) def create_branch_change_note(issuable, branch_type, event_type, old_branch, new_branch)
SystemNoteService.change_branch( SystemNoteService.change_branch(
issuable, issuable.project, current_user, branch_type, event_type, issuable, issuable.project, current_user, branch_type, event_type,
......
...@@ -58,5 +58,15 @@ module EE ...@@ -58,5 +58,15 @@ module EE
end end
end end
end end
override :allowed_create_params
def allowed_create_params(params)
super(params).except(:epic)
end
override :allowed_update_params
def allowed_update_params(params)
super(params).except(:epic)
end
end end
end end
...@@ -7,21 +7,16 @@ module EE ...@@ -7,21 +7,16 @@ module EE
class EpicAssignmentError < ::ArgumentError; end class EpicAssignmentError < ::ArgumentError; end
def handle_epic(issue) def filter_epic(issue)
return unless epic_param_present? return unless epic_param_present?
epic = epic_param(issue) epic = epic_param(issue)
result = epic ? assign_epic(issue, epic) : unassign_epic(issue)
issue.reload_epic
if result[:status] == :error params[:confidential] = true if !issue.persisted? && epic&.confidential
raise EpicAssignmentError, result[:message] params[:epic] = epic
end
end end
def assign_epic(issue, epic) def assign_epic(issue, epic)
issue.confidential = true if !issue.persisted? && epic.confidential
had_epic = issue.epic.present? had_epic = issue.epic.present?
link_params = { target_issuable: issue, skip_epic_dates_update: true } link_params = { target_issuable: issue, skip_epic_dates_update: true }
...@@ -86,6 +81,32 @@ module EE ...@@ -86,6 +81,32 @@ module EE
params[:sprint_id] = '' unless iteration params[:sprint_id] = '' unless iteration
end end
override :handle_changes
def handle_changes(issue, options)
handle_epic_change(issue, options)
end
def handle_epic_change(issue, options)
return unless epic_param_present?
old_epic = issue.epic
epic = options.dig(:params, :epic)
return if !epic && !old_epic
result = if old_epic && !epic
unassign_epic(issue)
else
assign_epic(issue, epic)
end
issue.reload_epic
if result[:status] == :error
raise EpicAssignmentError, result[:message]
end
end
end end
end end
end end
...@@ -7,7 +7,7 @@ module EE ...@@ -7,7 +7,7 @@ module EE
override :filter_params override :filter_params
def filter_params(issue) def filter_params(issue)
handle_epic(issue) filter_epic(issue)
super super
end end
......
...@@ -10,7 +10,7 @@ module EE ...@@ -10,7 +10,7 @@ module EE
def filter_params(issue) def filter_params(issue)
params.delete(:sprint_id) unless can_admin_issuable?(issue) params.delete(:sprint_id) unless can_admin_issuable?(issue)
handle_epic(issue) filter_epic(issue)
filter_iteration filter_iteration
super super
......
...@@ -167,6 +167,11 @@ RSpec.describe 'Issues > Bulk edit issues' do ...@@ -167,6 +167,11 @@ RSpec.describe 'Issues > Bulk edit issues' do
end end
context 'at group level' do context 'at group level' do
before do
# avoid raising QueryLimiting exception for bulk inserts
stub_const("::Gitlab::QueryLimiting::Transaction::THRESHOLD", 110)
end
it_behaves_like 'bulk edit option in sidebar', :group it_behaves_like 'bulk edit option in sidebar', :group
it_behaves_like 'bulk edit epic', :group it_behaves_like 'bulk edit epic', :group
it_behaves_like 'bulk edit health status', :group it_behaves_like 'bulk edit health status', :group
......
...@@ -4,9 +4,9 @@ require 'spec_helper' ...@@ -4,9 +4,9 @@ require 'spec_helper'
RSpec.describe Issues::CreateService do RSpec.describe Issues::CreateService do
let_it_be(:group) { create(:group) } let_it_be(:group) { create(:group) }
let_it_be(:user) { create(:user) }
let_it_be_with_reload(:project) { create(:project, group: group) }
let(:project) { create(:project, group: group) }
let(:user) { create(:user) }
let(:params) { { title: 'Awesome issue', description: 'please fix', weight: 9 } } let(:params) { { title: 'Awesome issue', description: 'please fix', weight: 9 } }
let(:service) { described_class.new(project: project, current_user: user, params: params) } let(:service) { described_class.new(project: project, current_user: user, params: params) }
...@@ -67,11 +67,17 @@ RSpec.describe Issues::CreateService do ...@@ -67,11 +67,17 @@ RSpec.describe Issues::CreateService do
end end
context 'with epic and milestone in commands only' do context 'with epic and milestone in commands only' do
let(:milestone) { create(:milestone, group: group, start_date: Date.today, due_date: 7.days.from_now) } let_it_be(:milestone) { create(:milestone, group: group, start_date: Date.today, due_date: 7.days.from_now) }
let_it_be(:assignee_user1) { create(:user) }
before do
project.add_guest(assignee_user1)
end
let(:params) do let(:params) do
{ {
title: 'Awesome issue', title: 'Awesome issue',
description: %(/epic #{epic.to_reference}\n/milestone #{milestone.to_reference}") description: %(/epic #{epic.to_reference}\n/milestone #{milestone.to_reference}\n/assign #{assignee_user1.to_reference})
} }
end end
...@@ -83,6 +89,20 @@ RSpec.describe Issues::CreateService do ...@@ -83,6 +89,20 @@ RSpec.describe Issues::CreateService do
expect(epic.reload.start_date).to eq(milestone.start_date) expect(epic.reload.start_date).to eq(milestone.start_date)
expect(epic.due_date).to eq(milestone.due_date) expect(epic.due_date).to eq(milestone.due_date)
end end
it 'generates system notes for adding an epic and milestone' do
expect { service.execute }.to change(Note, :count).by(3).and(change(ResourceMilestoneEvent, :count).by(1))
end
context 'when assigning epic raises an exception' do
let(:mock_service) { double('service', execute: { status: :error, message: 'failed to assign epic' }) }
it 'assigns the issue passed to the provided epic' do
expect(EpicIssues::CreateService).to receive(:new).and_return(mock_service)
expect { service.execute }.to raise_error(EE::Issues::BaseService::EpicAssignmentError, 'failed to assign epic')
end
end
end end
context 'when adding a public issue to confidential epic' do context 'when adding a public issue to confidential epic' do
......
...@@ -4,9 +4,10 @@ require 'spec_helper' ...@@ -4,9 +4,10 @@ require 'spec_helper'
RSpec.describe Issues::UpdateService do RSpec.describe Issues::UpdateService do
let_it_be(:group) { create(:group) } let_it_be(:group) { create(:group) }
let_it_be_with_reload(:project) { create(:project, group: group) }
let_it_be_with_reload(:issue) { create(:issue, project: project) }
let_it_be(:epic) { create(:epic, group: group) }
let(:project) { create(:project, group: group) }
let(:issue) { create(:issue, project: project) }
let(:author) { issue.author } let(:author) { issue.author }
let(:user) { author } let(:user) { author }
...@@ -20,12 +21,12 @@ RSpec.describe Issues::UpdateService do ...@@ -20,12 +21,12 @@ RSpec.describe Issues::UpdateService do
end end
context 'refresh epic dates' do context 'refresh epic dates' do
let_it_be(:epic) { create(:epic) } before do
issue.update!(epic: epic)
let(:issue) { create(:issue, epic: epic, project: project) } end
context 'updating milestone' do context 'updating milestone' do
let(:milestone) { create(:milestone, project: project) } let_it_be(:milestone) { create(:milestone, project: project) }
it 'calls UpdateDatesService' do it 'calls UpdateDatesService' do
expect(Epics::UpdateDatesService).to receive(:new).with([epic]).and_call_original.twice expect(Epics::UpdateDatesService).to receive(:new).with([epic]).and_call_original.twice
...@@ -36,7 +37,7 @@ RSpec.describe Issues::UpdateService do ...@@ -36,7 +37,7 @@ RSpec.describe Issues::UpdateService do
end end
context 'updating iteration' do context 'updating iteration' do
let(:iteration) { create(:iteration, group: group) } let_it_be(:iteration) { create(:iteration, group: group) }
context 'when issue does not already have an iteration' do context 'when issue does not already have an iteration' do
it 'calls NotificationService#changed_iteration_issue' do it 'calls NotificationService#changed_iteration_issue' do
...@@ -49,7 +50,7 @@ RSpec.describe Issues::UpdateService do ...@@ -49,7 +50,7 @@ RSpec.describe Issues::UpdateService do
end end
context 'when issue already has an iteration' do context 'when issue already has an iteration' do
let(:old_iteration) { create(:iteration, group: group) } let_it_be(:old_iteration) { create(:iteration, group: group) }
before do before do
update_issue(iteration: old_iteration) update_issue(iteration: old_iteration)
...@@ -96,7 +97,7 @@ RSpec.describe Issues::UpdateService do ...@@ -96,7 +97,7 @@ RSpec.describe Issues::UpdateService do
context 'updating weight' do context 'updating weight' do
before do before do
project.add_maintainer(user) project.add_maintainer(user)
issue.update(weight: 3) issue.update!(weight: 3)
end end
context 'when weight is integer' do context 'when weight is integer' do
...@@ -158,20 +159,20 @@ RSpec.describe Issues::UpdateService do ...@@ -158,20 +159,20 @@ RSpec.describe Issues::UpdateService do
end end
context 'group iterations' do context 'group iterations' do
let(:iteration) { create(:iteration, group: group) } let_it_be(:iteration) { create(:iteration, group: group) }
it_behaves_like 'creates iteration resource event' it_behaves_like 'creates iteration resource event'
end end
context 'project iterations' do context 'project iterations' do
let(:iteration) { create(:iteration, :skip_project_validation, project: project) } let_it_be(:iteration) { create(:iteration, :skip_project_validation, project: project) }
it_behaves_like 'creates iteration resource event' it_behaves_like 'creates iteration resource event'
end end
end end
context 'changing issue_type' do context 'changing issue_type' do
let!(:sla_setting) { create(:project_incident_management_setting, :sla_enabled, project: project) } let_it_be(:sla_setting) { create(:project_incident_management_setting, :sla_enabled, project: project) }
before do before do
stub_licensed_features(incident_sla: true, quality_management: true) stub_licensed_features(incident_sla: true, quality_management: true)
...@@ -186,8 +187,8 @@ RSpec.describe Issues::UpdateService do ...@@ -186,8 +187,8 @@ RSpec.describe Issues::UpdateService do
end end
context 'from incident to issue' do context 'from incident to issue' do
let(:issue) { create(:incident, project: project) } let_it_be(:issue) { create(:incident, project: project) }
let!(:sla) { create(:issuable_sla, issue: issue) } let_it_be(:sla) { create(:issuable_sla, issue: issue) }
it 'does not remove the SLA or create a new one' do it 'does not remove the SLA or create a new one' do
expect { update_issue(issue_type: 'issue') }.not_to change(IssuableSla, :count) expect { update_issue(issue_type: 'issue') }.not_to change(IssuableSla, :count)
...@@ -212,10 +213,12 @@ RSpec.describe Issues::UpdateService do ...@@ -212,10 +213,12 @@ RSpec.describe Issues::UpdateService do
end end
context 'without sufficient permissions' do context 'without sufficient permissions' do
let(:user) { create(:user) } let_it_be(:guest) { create(:user) }
let(:user) { guest }
before do before do
project.add_guest(user) project.add_guest(guest)
end end
it 'excludes the issue type param' do it 'excludes the issue type param' do
...@@ -230,9 +233,9 @@ RSpec.describe Issues::UpdateService do ...@@ -230,9 +233,9 @@ RSpec.describe Issues::UpdateService do
stub_licensed_features(epics: true) stub_licensed_features(epics: true)
end end
let(:epic) { create(:epic, group: group) } let(:params) { { epic: epic } }
subject { update_issue(epic: epic) } subject { update_issue(params) }
context 'when a user does not have permissions to assign an epic' do context 'when a user does not have permissions to assign an epic' do
it 'raises an exception' do it 'raises an exception' do
...@@ -282,7 +285,7 @@ RSpec.describe Issues::UpdateService do ...@@ -282,7 +285,7 @@ RSpec.describe Issues::UpdateService do
end end
context 'when issue belongs to another epic' do context 'when issue belongs to another epic' do
let(:epic2) { create(:epic, group: group) } let_it_be(:epic2) { create(:epic, group: group) }
before do before do
issue.update!(epic: epic2) issue.update!(epic: epic2)
...@@ -308,6 +311,52 @@ RSpec.describe Issues::UpdateService do ...@@ -308,6 +311,52 @@ RSpec.describe Issues::UpdateService do
subject subject
end end
end end
context 'when updating issue epic and milestone and assignee attributes' do
let_it_be(:milestone) { create(:milestone, project: project) }
let_it_be(:assignee_user1) { create(:user) }
let(:params) { { epic: epic, milestone: milestone, assignees: [assignee_user1] } }
before do
project.add_guest(assignee_user1)
end
it 'assigns the issue passed to the provided epic' do
expect do
subject
issue.reload
end.to change { issue.epic }.from(nil).to(epic)
.and(change { issue.milestone }.from(nil).to(milestone))
.and(change(ResourceMilestoneEvent, :count).by(1))
.and(change(Note, :count).by(3))
end
context 'when milestone and epic attributes are changed from description' do
let(:params) { { description: %(/epic #{epic.to_reference}\n/milestone #{milestone.to_reference}\n/assign #{assignee_user1.to_reference}) } }
it 'assigns the issue passed to the provided epic' do
expect do
subject
issue.reload
end.to change { issue.epic }.from(nil).to(epic)
.and(change { issue.assignees }.from([]).to([assignee_user1]))
.and(change { issue.milestone }.from(nil).to(milestone))
.and(change(ResourceMilestoneEvent, :count).by(1))
.and(change(Note, :count).by(4))
end
end
context 'when assigning epic raises an exception' do
let(:mock_service) { double('service', execute: { status: :error, message: 'failed to assign epic' }) }
it 'assigns the issue passed to the provided epic' do
expect(EpicIssues::CreateService).to receive(:new).and_return(mock_service)
expect { subject }.to raise_error(EE::Issues::BaseService::EpicAssignmentError, 'failed to assign epic')
end
end
end
end end
end end
...@@ -316,8 +365,6 @@ RSpec.describe Issues::UpdateService do ...@@ -316,8 +365,6 @@ RSpec.describe Issues::UpdateService do
stub_licensed_features(epics: true) stub_licensed_features(epics: true)
end end
let(:epic) { create(:epic, group: group) }
subject { update_issue(epic: nil) } subject { update_issue(epic: nil) }
context 'when a user has permissions to assign an epic' do context 'when a user has permissions to assign an epic' do
...@@ -338,7 +385,9 @@ RSpec.describe Issues::UpdateService do ...@@ -338,7 +385,9 @@ RSpec.describe Issues::UpdateService do
end end
context 'when issue belongs to an epic' do context 'when issue belongs to an epic' do
let!(:epic_issue) { create(:epic_issue, issue: issue, epic: epic)} before do
issue.update!(epic: epic)
end
it 'unassigns the epic' do it 'unassigns the epic' do
expect { subject }.to change { issue.reload.epic }.from(epic).to(nil) expect { subject }.to change { issue.reload.epic }.from(epic).to(nil)
...@@ -346,8 +395,7 @@ RSpec.describe Issues::UpdateService do ...@@ -346,8 +395,7 @@ RSpec.describe Issues::UpdateService do
it 'calls EpicIssues::DestroyService' do it 'calls EpicIssues::DestroyService' do
link_sevice = double link_sevice = double
expect(EpicIssues::DestroyService).to receive(:new).with(EpicIssue.last, user) expect(EpicIssues::DestroyService).to receive(:new).with(EpicIssue.last, user).and_return(link_sevice)
.and_return(link_sevice)
expect(link_sevice).to receive(:execute).and_return({ status: :success }) expect(link_sevice).to receive(:execute).and_return({ status: :success })
subject subject
...@@ -362,10 +410,8 @@ RSpec.describe Issues::UpdateService do ...@@ -362,10 +410,8 @@ RSpec.describe Issues::UpdateService do
context 'but EpicIssues::DestroyService returns failure', :aggregate_failures do context 'but EpicIssues::DestroyService returns failure', :aggregate_failures do
it 'does not send usage data for removed epic action' do it 'does not send usage data for removed epic action' do
link_sevice = double link_sevice = double
expect(EpicIssues::DestroyService).to receive(:new).with(EpicIssue.last, user) expect(EpicIssues::DestroyService).to receive(:new).with(EpicIssue.last, user).and_return(link_sevice)
.and_return(link_sevice)
expect(link_sevice).to receive(:execute).and_return({ status: :failure }) expect(link_sevice).to receive(:execute).and_return({ status: :failure })
expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_removed_from_epic_action) expect(Gitlab::UsageDataCounters::IssueActivityUniqueCounter).not_to receive(:track_issue_removed_from_epic_action)
subject subject
...@@ -382,17 +428,16 @@ RSpec.describe Issues::UpdateService do ...@@ -382,17 +428,16 @@ RSpec.describe Issues::UpdateService do
it_behaves_like 'issue with epic_id parameter' do it_behaves_like 'issue with epic_id parameter' do
let(:execute) { described_class.new(project: project, current_user: user, params: params).execute(issue) } let(:execute) { described_class.new(project: project, current_user: user, params: params).execute(issue) }
let(:epic) { create(:epic, group: group) }
end end
context 'when epic_id is nil' do context 'when epic_id is nil' do
before do before do
stub_licensed_features(epics: true) stub_licensed_features(epics: true)
group.add_maintainer(user) group.add_maintainer(user)
issue.update!(epic: epic)
end end
let(:epic) { create(:epic, group: group) } let(:epic_issue) { issue.epic_issue }
let!(:epic_issue) { create(:epic_issue, epic: epic, issue: issue) }
let(:params) { { epic_id: nil } } let(:params) { { epic_id: nil } }
subject { update_issue(params) } subject { update_issue(params) }
...@@ -403,8 +448,7 @@ RSpec.describe Issues::UpdateService do ...@@ -403,8 +448,7 @@ RSpec.describe Issues::UpdateService do
it 'calls EpicIssues::DestroyService' do it 'calls EpicIssues::DestroyService' do
link_sevice = double link_sevice = double
expect(EpicIssues::DestroyService).to receive(:new).with(epic_issue, user) expect(EpicIssues::DestroyService).to receive(:new).with(epic_issue, user).and_return(link_sevice)
.and_return(link_sevice)
expect(link_sevice).to receive(:execute).and_return({ status: :success }) expect(link_sevice).to receive(:execute).and_return({ status: :success })
subject subject
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment