debian-mirror-gitlab/spec/services/issues/create_service_spec.rb

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

861 lines
28 KiB
Ruby
Raw Normal View History

2019-07-31 22:56:46 +05:30
# frozen_string_literal: true
2014-09-02 18:07:02 +05:30
require 'spec_helper'
2023-05-27 22:25:52 +05:30
RSpec.describe Issues::CreateService, feature_category: :team_planning do
2021-04-29 21:17:54 +05:30
include AfterNextHelpers
2022-03-02 08:16:31 +05:30
let_it_be(:group) { create(:group, :crm_enabled) }
2022-11-25 23:54:43 +05:30
let_it_be_with_reload(:project) { create(:project, :public, group: group) }
2020-11-24 15:15:51 +05:30
let_it_be(:user) { create(:user) }
2014-09-02 18:07:02 +05:30
2023-03-04 22:38:38 +05:30
let(:opts) { { title: 'title' } }
2021-09-30 23:02:18 +05:30
let(:spam_params) { double }
2023-04-23 21:23:45 +05:30
let(:service) { described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params) }
2021-09-30 23:02:18 +05:30
2022-05-07 20:08:51 +05:30
it_behaves_like 'rate limited service' do
let(:key) { :issues_create }
let(:key_scope) { %i[project current_user external_author] }
let(:application_limit_key) { :issues_create_limit }
let(:created_model) { Issue }
2021-11-18 22:05:49 +05:30
end
2016-06-02 11:05:42 +05:30
describe '#execute' do
2020-11-24 15:15:51 +05:30
let_it_be(:assignee) { create(:user) }
let_it_be(:milestone) { create(:milestone, project: project) }
2021-04-29 21:17:54 +05:30
2023-03-04 22:38:38 +05:30
let(:result) { service.execute }
2022-11-25 23:54:43 +05:30
let(:issue) { result[:issue] }
2021-09-30 23:02:18 +05:30
before do
stub_spam_services
end
2016-06-02 11:05:42 +05:30
2022-11-25 23:54:43 +05:30
context 'when params are invalid' do
let(:opts) { { title: '' } }
before_all do
project.add_guest(assignee)
end
it 'returns an error service response' do
expect(result).to be_error
expect(result.errors).to include("Title can't be blank")
expect(issue).not_to be_persisted
end
end
2016-06-02 11:05:42 +05:30
context 'when params are valid' do
2020-11-24 15:15:51 +05:30
let_it_be(:labels) { create_pair(:label, project: project) }
2016-06-02 11:05:42 +05:30
2020-11-24 15:15:51 +05:30
before_all do
2021-09-04 01:27:46 +05:30
project.add_guest(user)
project.add_guest(assignee)
2016-06-02 11:05:42 +05:30
end
2016-04-02 18:10:28 +05:30
2016-06-02 11:05:42 +05:30
let(:opts) do
{ title: 'Awesome issue',
2023-03-04 22:38:38 +05:30
issue_type: :task,
2016-04-02 18:10:28 +05:30
description: 'please fix',
2017-08-17 22:00:37 +05:30
assignee_ids: [assignee.id],
2016-06-02 11:05:42 +05:30
label_ids: labels.map(&:id),
2016-11-03 12:29:30 +05:30
milestone_id: milestone.id,
2020-10-04 03:57:07 +05:30
milestone: milestone,
2016-11-03 12:29:30 +05:30
due_date: Date.tomorrow }
2014-09-02 18:07:02 +05:30
end
2022-10-02 17:18:49 +05:30
context 'when an unauthorized project_id is provided' do
let(:unauthorized_project) { create(:project) }
before do
opts[:project_id] = unauthorized_project.id
end
it 'ignores the project_id param and creates issue in the given project' do
expect(issue.project).to eq(project)
expect(unauthorized_project.reload.issues.count).to eq(0)
end
end
2022-11-25 23:54:43 +05:30
describe 'authorization' do
let_it_be(:project) { create(:project, :private, group: group).tap { |project| project.add_guest(user) } }
let(:opts) { { title: 'private issue', description: 'please fix' } }
context 'when the user is authorized' do
it 'allows the user to create an issue' do
expect(result).to be_success
expect(issue).to be_persisted
end
end
context 'when the user is not authorized' do
let(:user) { create(:user) }
it 'does not allow the user to create an issue' do
expect(result).to be_error
expect(result.errors).to contain_exactly('Operation not allowed')
expect(result.http_status).to eq(403)
expect(issue).to be_nil
end
end
end
2022-07-16 23:28:13 +05:30
it 'works if base work item types were not created yet' do
WorkItems::Type.delete_all
expect do
issue
end.to change(Issue, :count).by(1)
end
2016-11-03 12:29:30 +05:30
it 'creates the issue with the given params' do
2020-11-24 15:15:51 +05:30
expect(Issuable::CommonSystemNotesService).to receive_message_chain(:new, :execute)
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2016-11-03 12:29:30 +05:30
expect(issue).to be_persisted
2022-03-02 08:16:31 +05:30
expect(issue).to be_a(::Issue)
2016-11-03 12:29:30 +05:30
expect(issue.title).to eq('Awesome issue')
2021-11-11 11:23:49 +05:30
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)
2023-03-04 22:38:38 +05:30
expect(issue.work_item_type.base_type).to eq('task')
2022-07-23 23:45:48 +05:30
expect(issue.issue_customer_relations_contacts).to be_empty
2016-11-03 12:29:30 +05:30
end
2023-06-20 00:43:36 +05:30
context 'with milestone' do
it 'deletes milestone issues count cache' do
expect_next(Milestones::IssuesCountService, milestone)
.to receive(:delete_cache).and_call_original
expect(result).to be_success
end
end
2023-03-04 22:38:38 +05:30
context 'when the work item type is not allowed to create' do
before do
allow_next_instance_of(::Issues::BuildService) do |instance|
allow(instance).to receive(:create_issue_type_allowed?).twice.and_return(false)
end
end
it 'ignores the type and creates default issue' do
expect(result).to be_success
expect(issue).to be_persisted
expect(issue).to be_a(::Issue)
expect(issue.work_item_type.base_type).to eq('issue')
end
end
2022-08-27 11:52:29 +05:30
it 'calls NewIssueWorker with correct arguments' do
expect(NewIssueWorker).to receive(:perform_async).with(Integer, user.id, 'Issue')
issue
end
2022-03-02 08:16:31 +05:30
context 'when a build_service is provided' do
2023-04-23 21:23:45 +05:30
let(:result) { described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params, build_service: build_service).execute }
2022-03-02 08:16:31 +05:30
2023-07-09 08:55:56 +05:30
let(:issue_from_builder) { build(:work_item, project: project, title: 'Issue from builder') }
2022-03-02 08:16:31 +05:30
let(:build_service) { double(:build_service, execute: issue_from_builder) }
it 'uses the provided service to build the issue' do
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2022-03-02 08:16:31 +05:30
expect(issue).to be_persisted
expect(issue).to be_a(WorkItem)
end
end
2020-11-24 15:15:51 +05:30
context 'when skip_system_notes is true' do
2023-04-23 21:23:45 +05:30
let(:issue) { described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute(skip_system_notes: true) }
2020-11-24 15:15:51 +05:30
it 'does not call Issuable::CommonSystemNotesService' do
expect(Issuable::CommonSystemNotesService).not_to receive(:new)
issue
end
end
2022-04-04 11:22:00 +05:30
context 'when setting a position' do
let(:issue_before) { create(:issue, project: project, relative_position: 10) }
let(:issue_after) { create(:issue, project: project, relative_position: 50) }
before do
opts.merge!(move_between_ids: [issue_before.id, issue_after.id])
end
it 'sets the correct relative position' do
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2022-04-04 11:22:00 +05:30
expect(issue).to be_persisted
expect(issue.relative_position).to be_present
expect(issue.relative_position).to be_between(issue_before.relative_position, issue_after.relative_position)
end
end
2020-11-24 15:15:51 +05:30
it_behaves_like 'not an incident issue'
2021-12-11 22:18:48 +05:30
context 'when issue is incident type' do
2020-11-24 15:15:51 +05:30
before do
opts.merge!(issue_type: 'incident')
end
let(:current_user) { user }
subject { issue }
2021-12-11 22:18:48 +05:30
context 'as reporter' do
let_it_be(:reporter) { create(:user) }
2020-11-24 15:15:51 +05:30
2021-12-11 22:18:48 +05:30
let(:user) { reporter }
2020-11-24 15:15:51 +05:30
2021-12-11 22:18:48 +05:30
before_all do
project.add_reporter(reporter)
2020-11-24 15:15:51 +05:30
end
2021-12-11 22:18:48 +05:30
it_behaves_like 'incident issue'
2022-01-26 12:08:38 +05:30
it 'calls IncidentManagement::Incidents::CreateEscalationStatusService' do
expect_next(::IncidentManagement::IssuableEscalationStatuses::CreateService, a_kind_of(Issue))
.to receive(:execute)
issue
end
2022-08-13 15:12:31 +05:30
it 'calls IncidentManagement::TimelineEvents::CreateService.create_incident' do
expect(IncidentManagement::TimelineEvents::CreateService)
.to receive(:create_incident)
.with(a_kind_of(Issue), reporter)
issue
end
2022-08-27 11:52:29 +05:30
it 'calls NewIssueWorker with correct arguments' do
expect(NewIssueWorker).to receive(:perform_async).with(Integer, reporter.id, 'Issue')
issue
end
2021-12-11 22:18:48 +05:30
context 'when invalid' do
before do
opts.merge!(title: '')
end
it 'does not apply an incident label prematurely' do
expect { subject }.to not_change(LabelLink, :count).and not_change(Issue, :count)
end
2020-11-24 15:15:51 +05:30
end
end
2021-12-11 22:18:48 +05:30
context 'as guest' do
it_behaves_like 'not an incident issue'
end
2020-11-24 15:15:51 +05:30
end
2018-03-17 18:26:18 +05:30
it 'refreshes the number of open issues', :use_clean_rails_memory_store_caching do
2021-11-11 11:23:49 +05:30
expect do
issue
BatchLoader::Executor.clear_current
end.to change { project.open_issues_count }.from(0).to(1)
2018-03-17 18:26:18 +05:30
end
2021-09-04 01:27:46 +05:30
context 'when current user cannot set issue metadata in the project' do
let_it_be(:non_member) { create(:user) }
2017-08-17 22:00:37 +05:30
2021-09-04 01:27:46 +05:30
it 'filters out params that cannot be set without the :set_issue_metadata permission' do
2023-04-23 21:23:45 +05:30
result = described_class.new(container: project, current_user: non_member, params: opts, spam_params: spam_params).execute
2022-11-25 23:54:43 +05:30
issue = result[:issue]
2016-11-03 12:29:30 +05:30
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2016-11-03 12:29:30 +05:30
expect(issue).to be_persisted
expect(issue.title).to eq('Awesome issue')
2017-08-17 22:00:37 +05:30
expect(issue.description).to eq('please fix')
expect(issue.assignees).to be_empty
2016-11-03 12:29:30 +05:30
expect(issue.labels).to be_empty
expect(issue.milestone).to be_nil
expect(issue.due_date).to be_nil
end
2020-10-04 03:57:07 +05:30
2021-09-04 01:27:46 +05:30
it 'can create confidential issues' do
2023-04-23 21:23:45 +05:30
result = described_class.new(container: project, current_user: non_member, params: opts.merge(confidential: true), spam_params: spam_params).execute
2022-11-25 23:54:43 +05:30
issue = result[:issue]
2020-10-04 03:57:07 +05:30
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2020-10-04 03:57:07 +05:30
expect(issue.confidential).to be_truthy
end
2016-11-03 12:29:30 +05:30
end
2016-04-02 18:10:28 +05:30
2020-11-24 15:15:51 +05:30
it 'moves the issue to the end, in an asynchronous worker' do
2022-01-26 12:08:38 +05:30
expect(Issues::PlacementWorker).to receive(:perform_async).with(be_nil, Integer)
2020-11-24 15:15:51 +05:30
2023-04-23 21:23:45 +05:30
described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
2020-11-24 15:15:51 +05:30
end
2016-11-03 12:29:30 +05:30
context 'when label belongs to project group' do
let(:group) { create(:group) }
let(:group_labels) { create_pair(:group_label, group: group) }
let(:opts) do
{
title: 'Title',
description: 'Description',
label_ids: group_labels.map(&:id)
}
end
before do
2020-11-24 15:15:51 +05:30
project.update!(group: group)
2016-11-03 12:29:30 +05:30
end
it 'assigns group labels' do
expect(issue.labels).to match_array group_labels
end
end
2016-06-02 11:05:42 +05:30
context 'when label belongs to different project' do
let(:label) { create(:label) }
let(:opts) do
{ title: 'Title',
description: 'Description',
label_ids: [label.id] }
end
it 'does not assign label' do
expect(issue.labels).not_to include label
2016-06-02 11:05:42 +05:30
end
end
2020-05-24 23:13:21 +05:30
context 'when labels is nil' do
let(:opts) do
{ title: 'Title',
description: 'Description',
labels: nil }
end
it 'does not assign label' do
expect(issue.labels).to be_empty
end
end
context 'when labels is nil and label_ids is present' do
let(:opts) do
{ title: 'Title',
description: 'Description',
labels: nil,
label_ids: labels.map(&:id) }
end
it 'assigns group labels' do
expect(issue.labels).to match_array labels
end
end
2016-06-02 11:05:42 +05:30
context 'when milestone belongs to different project' do
let(:milestone) { create(:milestone) }
let(:opts) do
{ title: 'Title',
description: 'Description',
milestone_id: milestone.id }
end
it 'does not assign milestone' do
expect(issue.milestone).not_to eq milestone
2016-06-02 11:05:42 +05:30
end
end
2016-09-29 09:46:39 +05:30
2017-08-17 22:00:37 +05:30
context 'when assignee is set' do
let(:opts) do
{ title: 'Title',
description: 'Description',
2022-11-25 23:54:43 +05:30
assignee_ids: [assignee.id] }
2017-08-17 22:00:37 +05:30
end
it 'invalidates open issues counter for assignees when issue is assigned' do
2018-11-18 11:00:15 +05:30
project.add_maintainer(assignee)
2017-08-17 22:00:37 +05:30
2023-04-23 21:23:45 +05:30
described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
2017-08-17 22:00:37 +05:30
expect(assignee.assigned_open_issues_count).to eq 1
end
2023-06-20 00:43:36 +05:30
it 'records the assignee assignment event' do
result = described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
issue = result.payload[:issue]
expect(issue.assignment_events).to match([have_attributes(user_id: assignee.id, action: 'add')])
end
2017-08-17 22:00:37 +05:30
end
2019-07-07 11:18:12 +05:30
context 'when duplicate label titles are given' do
let(:label) { create(:label, project: project) }
let(:opts) do
{ title: 'Title',
description: 'Description',
labels: [label.title, label.title] }
end
it 'assigns the label once' do
expect(issue.labels).to contain_exactly(label)
end
end
2021-08-04 16:29:09 +05:30
context 'when sentry identifier is given' do
before do
sentry_attributes = { sentry_issue_attributes: { sentry_issue_identifier: 42 } }
opts.merge!(sentry_attributes)
end
2021-09-04 01:27:46 +05:30
it 'does not assign the sentry error' do
expect(issue.sentry_issue).to eq(nil)
end
context 'user is reporter or above' do
2021-08-04 16:29:09 +05:30
before do
2022-07-01 11:34:44 +05:30
project.add_developer(user)
2021-08-04 16:29:09 +05:30
end
2021-09-04 01:27:46 +05:30
it 'assigns the sentry error' do
expect(issue.sentry_issue).to be_kind_of(SentryIssue)
2021-08-04 16:29:09 +05:30
end
end
end
2023-01-13 00:05:48 +05:30
describe 'executing hooks' do
let(:opts) { { title: 'Title', description: 'Description' } }
let(:expected_payload) do
include(
event_type: 'issue',
object_kind: 'issue',
changes: {
author_id: { current: user.id, previous: nil },
created_at: { current: kind_of(Time), previous: nil },
description: { current: opts[:description], previous: nil },
id: { current: kind_of(Integer), previous: nil },
iid: { current: kind_of(Integer), previous: nil },
project_id: { current: project.id, previous: nil },
title: { current: opts[:title], previous: nil },
2023-03-04 22:38:38 +05:30
updated_at: { current: kind_of(Time), previous: nil },
time_estimate: { current: 0, previous: nil }
2023-01-13 00:05:48 +05:30
},
object_attributes: include(
opts.merge(
author_id: user.id,
project_id: project.id
)
)
)
end
2016-09-29 09:46:39 +05:30
2023-01-13 00:05:48 +05:30
it 'executes issue hooks' do
2023-06-20 00:43:36 +05:30
expect(project.project_namespace).to receive(:execute_hooks).with(expected_payload, :issue_hooks)
expect(project.project_namespace).to receive(:execute_integrations).with(expected_payload, :issue_hooks)
2016-09-29 09:46:39 +05:30
2023-04-23 21:23:45 +05:30
described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
2023-01-13 00:05:48 +05:30
end
context 'when issue is confidential' do
let(:expected_payload) do
include(
event_type: 'confidential_issue',
object_kind: 'issue',
changes: include(
confidential: { current: true, previous: false }
),
object_attributes: include(confidential: true)
)
end
2016-09-29 09:46:39 +05:30
2023-01-13 00:05:48 +05:30
before do
opts[:confidential] = true
end
2016-09-29 09:46:39 +05:30
2023-01-13 00:05:48 +05:30
it 'executes confidential issue hooks' do
2023-06-20 00:43:36 +05:30
expect(project.project_namespace).to receive(:execute_hooks).with(expected_payload, :confidential_issue_hooks)
expect(project.project_namespace).to receive(:execute_integrations).with(expected_payload, :confidential_issue_hooks)
2016-09-29 09:46:39 +05:30
2023-04-23 21:23:45 +05:30
described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
2023-01-13 00:05:48 +05:30
end
end
2016-09-29 09:46:39 +05:30
end
2020-03-13 15:44:24 +05:30
context 'after_save callback to store_mentions' do
context 'when mentionable attributes change' do
let(:opts) { { title: 'Title', description: "Description with #{user.to_reference}" } }
it 'saves mentions' do
expect_next_instance_of(Issue) do |instance|
expect(instance).to receive(:store_mentions!).and_call_original
end
expect(issue.user_mentions.count).to eq 1
end
end
context 'when save fails' do
let(:opts) { { title: '', label_ids: labels.map(&:id), milestone_id: milestone.id } }
it 'does not call store_mentions' do
expect_next_instance_of(Issue) do |instance|
expect(instance).not_to receive(:store_mentions!).and_call_original
end
expect(issue.valid?).to be false
expect(issue.user_mentions.count).to eq 0
end
end
end
2020-04-08 14:13:33 +05:30
2021-04-17 20:07:23 +05:30
it 'schedules a namespace onboarding create action worker' do
2023-06-20 00:43:36 +05:30
expect(Onboarding::IssueCreatedWorker).to receive(:perform_async).with(project.project_namespace_id)
2021-04-17 20:07:23 +05:30
issue
end
2014-09-02 18:07:02 +05:30
end
2016-09-13 17:45:13 +05:30
2017-08-17 22:00:37 +05:30
context 'issue create service' do
context 'assignees' do
2020-11-24 15:15:51 +05:30
before_all do
2018-11-18 11:00:15 +05:30
project.add_maintainer(user)
2017-09-10 17:25:29 +05:30
end
2017-08-17 22:00:37 +05:30
it 'removes assignee when user id is invalid' do
opts = { title: 'Title', description: 'Description', assignee_ids: [-1] }
2023-04-23 21:23:45 +05:30
result = described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
2022-11-25 23:54:43 +05:30
issue = result[:issue]
2017-08-17 22:00:37 +05:30
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2017-08-17 22:00:37 +05:30
expect(issue.assignees).to be_empty
end
it 'removes assignee when user id is 0' do
2019-03-02 22:35:43 +05:30
opts = { title: 'Title', description: 'Description', assignee_ids: [0] }
2017-08-17 22:00:37 +05:30
2023-04-23 21:23:45 +05:30
result = described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
2022-11-25 23:54:43 +05:30
issue = result[:issue]
2017-08-17 22:00:37 +05:30
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2017-08-17 22:00:37 +05:30
expect(issue.assignees).to be_empty
end
it 'saves assignee when user id is valid' do
2018-11-18 11:00:15 +05:30
project.add_maintainer(assignee)
2017-08-17 22:00:37 +05:30
opts = { title: 'Title', description: 'Description', assignee_ids: [assignee.id] }
2023-04-23 21:23:45 +05:30
result = described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
2022-11-25 23:54:43 +05:30
issue = result[:issue]
2017-08-17 22:00:37 +05:30
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2017-08-17 22:00:37 +05:30
expect(issue.assignees).to eq([assignee])
end
context "when issuable feature is private" do
before do
2020-11-24 15:15:51 +05:30
project.project_feature.update!(issues_access_level: ProjectFeature::PRIVATE,
2022-10-11 01:57:18 +05:30
merge_requests_access_level: ProjectFeature::PRIVATE)
2017-08-17 22:00:37 +05:30
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
2020-11-24 15:15:51 +05:30
project.update!(visibility_level: level)
2017-08-17 22:00:37 +05:30
opts = { title: 'Title', description: 'Description', assignee_ids: [assignee.id] }
2023-04-23 21:23:45 +05:30
result = described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
2022-11-25 23:54:43 +05:30
issue = result[:issue]
2017-08-17 22:00:37 +05:30
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2017-08-17 22:00:37 +05:30
expect(issue.assignees).to be_empty
end
end
end
end
end
2020-07-28 23:09:34 +05:30
it_behaves_like 'issuable record that supports quick actions' do
2023-04-23 21:23:45 +05:30
let(:issuable) { described_class.new(container: project, current_user: user, params: params, spam_params: spam_params).execute[:issue] }
2020-07-28 23:09:34 +05:30
end
2017-08-17 22:00:37 +05:30
2017-09-10 17:25:29 +05:30
context 'Quick actions' do
2022-01-26 12:08:38 +05:30
context 'with assignee, milestone, and contact in params and command' do
let_it_be(:contact) { create(:contact, group: group) }
2017-08-17 22:00:37 +05:30
let(:opts) do
{
assignee_ids: [create(:user).id],
milestone_id: 1,
title: 'Title',
2022-01-26 12:08:38 +05:30
description: %(/assign @#{assignee.username}\n/milestone %"#{milestone.name}"),
add_contacts: [contact.email]
2017-08-17 22:00:37 +05:30
}
end
2020-11-24 15:15:51 +05:30
before_all do
2022-01-26 12:08:38 +05:30
group.add_maintainer(user)
2018-11-18 11:00:15 +05:30
project.add_maintainer(assignee)
2017-08-17 22:00:37 +05:30
end
2022-01-26 12:08:38 +05:30
it 'assigns, sets milestone, and sets contact to issuable from command' do
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2017-08-17 22:00:37 +05:30
expect(issue).to be_persisted
expect(issue.assignees).to eq([assignee])
expect(issue.milestone).to eq(milestone)
2022-01-26 12:08:38 +05:30
expect(issue.issue_customer_relations_contacts.last.contact).to eq(contact)
2017-08-17 22:00:37 +05:30
end
end
2022-07-23 23:45:48 +05:30
context 'with external_author' do
let_it_be(:contact) { create(:contact, group: group) }
context 'when CRM contact exists with matching e-mail' do
let(:opts) do
{
title: 'Title',
external_author: contact.email
}
end
context 'with permission' do
it 'assigns contact to issue' do
group.add_reporter(user)
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2022-07-23 23:45:48 +05:30
expect(issue).to be_persisted
expect(issue.issue_customer_relations_contacts.last.contact).to eq(contact)
end
end
context 'without permission' do
it 'does not assign contact to issue' do
group.add_guest(user)
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2022-07-23 23:45:48 +05:30
expect(issue).to be_persisted
expect(issue.issue_customer_relations_contacts).to be_empty
end
end
end
context 'when no CRM contact exists with matching e-mail' do
let(:opts) do
{
title: 'Title',
external_author: 'example@gitlab.com'
}
end
it 'does not assign contact to issue' do
group.add_reporter(user)
expect(issue).to be_persisted
expect(issue.issue_customer_relations_contacts).to be_empty
end
end
end
2022-08-13 15:12:31 +05:30
context 'with alert bot author' do
let_it_be(:user) { User.alert_bot }
let_it_be(:label) { create(:label, project: project) }
let(:opts) do
{
title: 'Title',
description: %(/label #{label.to_reference(format: :name)}")
}
end
it 'can apply labels' do
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2022-08-13 15:12:31 +05:30
expect(issue).to be_persisted
expect(issue.labels).to eq([label])
end
end
2023-06-20 00:43:36 +05:30
context 'when using promote_to_incident' do
let(:opts) { { title: 'Title', description: '/promote_to_incident' } }
before do
project.add_developer(user)
end
it 'creates an issue with the correct issue type' do
expect { result }.to change(Issue, :count).by(1)
created_issue = Issue.last
expect(created_issue.work_item_type).to eq(WorkItems::Type.default_by_type('incident'))
end
end
2017-08-17 22:00:37 +05:30
end
context 'resolving discussions' do
2020-11-24 15:15:51 +05:30
let_it_be(:discussion) { create(:diff_note_on_merge_request).to_discussion }
let_it_be(:merge_request) { discussion.noteable }
let_it_be(:project) { merge_request.source_project }
2017-08-17 22:00:37 +05:30
2020-11-24 15:15:51 +05:30
before_all do
2018-11-18 11:00:15 +05:30
project.add_maintainer(user)
2017-08-17 22:00:37 +05:30
end
describe 'for a single discussion' do
let(:opts) { { discussion_to_resolve: discussion.id, merge_request_to_resolve_discussions_of: merge_request.iid } }
it 'resolves the discussion' do
2023-04-23 21:23:45 +05:30
described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
2017-08-17 22:00:37 +05:30
discussion.first_note.reload
expect(discussion.resolved?).to be(true)
end
it 'added a system note to the discussion' do
2023-04-23 21:23:45 +05:30
described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
2017-08-17 22:00:37 +05:30
reloaded_discussion = MergeRequest.find(merge_request.id).discussions.first
expect(reloaded_discussion.last_note.system).to eq(true)
end
2022-10-11 01:57:18 +05:30
it 'sets default title and description values if not provided' do
2022-11-25 23:54:43 +05:30
result = described_class.new(
2023-04-23 21:23:45 +05:30
container: project, current_user: user,
2022-10-11 01:57:18 +05:30
params: opts,
spam_params: spam_params
).execute
2022-11-25 23:54:43 +05:30
issue = result[:issue]
2017-08-17 22:00:37 +05:30
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2022-10-11 01:57:18 +05:30
expect(issue).to be_persisted
expect(issue.title).to eq("Follow-up from \"#{merge_request.title}\"")
expect(issue.description).to include("The following discussion from #{merge_request.to_reference} should be addressed")
2017-08-17 22:00:37 +05:30
end
2022-10-11 01:57:18 +05:30
it 'takes params from the request over the default values' do
2022-11-25 23:54:43 +05:30
result = described_class.new(
2023-04-23 21:23:45 +05:30
container: project,
2022-11-25 23:54:43 +05:30
current_user: user,
params: opts.merge(
description: 'Custom issue description',
title: 'My new issue'
),
spam_params: spam_params
).execute
issue = result[:issue]
2017-08-17 22:00:37 +05:30
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2022-10-11 01:57:18 +05:30
expect(issue).to be_persisted
expect(issue.description).to eq('Custom issue description')
expect(issue.title).to eq('My new issue')
2017-08-17 22:00:37 +05:30
end
end
describe 'for a merge request' do
let(:opts) { { merge_request_to_resolve_discussions_of: merge_request.iid } }
it 'resolves the discussion' do
2023-04-23 21:23:45 +05:30
described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
2017-08-17 22:00:37 +05:30
discussion.first_note.reload
expect(discussion.resolved?).to be(true)
end
it 'added a system note to the discussion' do
2023-04-23 21:23:45 +05:30
described_class.new(container: project, current_user: user, params: opts, spam_params: spam_params).execute
2017-08-17 22:00:37 +05:30
reloaded_discussion = MergeRequest.find(merge_request.id).discussions.first
expect(reloaded_discussion.last_note.system).to eq(true)
end
2022-10-11 01:57:18 +05:30
it 'sets default title and description values if not provided' do
2022-11-25 23:54:43 +05:30
result = described_class.new(
2023-04-23 21:23:45 +05:30
container: project, current_user: user,
2022-10-11 01:57:18 +05:30
params: opts,
spam_params: spam_params
).execute
2022-11-25 23:54:43 +05:30
issue = result[:issue]
2017-08-17 22:00:37 +05:30
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2022-10-11 01:57:18 +05:30
expect(issue).to be_persisted
expect(issue.title).to eq("Follow-up from \"#{merge_request.title}\"")
expect(issue.description).to include("The following discussion from #{merge_request.to_reference} should be addressed")
2017-08-17 22:00:37 +05:30
end
2022-10-11 01:57:18 +05:30
it 'takes params from the request over the default values' do
2022-11-25 23:54:43 +05:30
result = described_class.new(
2023-04-23 21:23:45 +05:30
container: project,
2022-11-25 23:54:43 +05:30
current_user: user,
params: opts.merge(
description: 'Custom issue description',
title: 'My new issue'
),
spam_params: spam_params
).execute
issue = result[:issue]
2017-08-17 22:00:37 +05:30
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2022-10-11 01:57:18 +05:30
expect(issue).to be_persisted
expect(issue.description).to eq('Custom issue description')
expect(issue.title).to eq('My new issue')
2017-08-17 22:00:37 +05:30
end
end
end
2022-05-07 20:08:51 +05:30
context 'add related issue' do
let_it_be(:related_issue) { create(:issue, project: project) }
let(:opts) do
{ title: 'A new issue', add_related_issue: related_issue }
end
it 'ignores related issue if not accessible' do
expect { issue }.not_to change { IssueLink.count }
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2022-05-07 20:08:51 +05:30
expect(issue).to be_persisted
end
context 'when user has access to the related issue' do
before do
project.add_developer(user)
end
it 'adds a link to the issue' do
expect { issue }.to change { IssueLink.count }.by(1)
2022-11-25 23:54:43 +05:30
expect(result).to be_success
2022-05-07 20:08:51 +05:30
expect(issue).to be_persisted
expect(issue.related_issues(user)).to eq([related_issue])
end
end
end
2017-08-17 22:00:37 +05:30
context 'checking spam' do
2021-03-11 19:13:27 +05:30
let(:params) do
2017-08-17 22:00:37 +05:30
{
2021-09-30 23:02:18 +05:30
title: 'Spam issue'
2017-08-17 22:00:37 +05:30
}
end
2021-03-11 19:13:27 +05:30
subject do
2023-04-23 21:23:45 +05:30
described_class.new(container: project, current_user: user, params: params, spam_params: spam_params)
2017-08-17 22:00:37 +05:30
end
2021-03-11 19:13:27 +05:30
it 'executes SpamActionService' do
expect_next_instance_of(
Spam::SpamActionService,
{
2021-09-30 23:02:18 +05:30
spammable: kind_of(Issue),
spam_params: spam_params,
user: an_instance_of(User),
2021-03-11 19:13:27 +05:30
action: :create
}
) do |instance|
2021-09-30 23:02:18 +05:30
expect(instance).to receive(:execute)
2017-08-17 22:00:37 +05:30
end
2021-03-11 19:13:27 +05:30
subject.execute
2017-08-17 22:00:37 +05:30
end
end
2014-09-02 18:07:02 +05:30
end
end