1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
# frozen_string_literal: true
require 'spec_helper'
describe Gitlab::SlashCommands::IssueMove, service: true do
describe '#match' do
shared_examples_for 'move command' do |text_command|
it 'can be parsed to extract the needed fields' do
match_data = described_class.match(text_command)
expect(match_data['iid']).to eq('123456')
expect(match_data['project_path']).to eq('gitlab/gitlab-ci')
end
end
it_behaves_like 'move command', 'issue move #123456 to gitlab/gitlab-ci'
it_behaves_like 'move command', 'issue move #123456 gitlab/gitlab-ci'
it_behaves_like 'move command', 'issue move #123456 gitlab/gitlab-ci '
it_behaves_like 'move command', 'issue move 123456 to gitlab/gitlab-ci'
it_behaves_like 'move command', 'issue move 123456 gitlab/gitlab-ci'
it_behaves_like 'move command', 'issue move 123456 gitlab/gitlab-ci '
end
describe '#execute' do
let_it_be(:user) { create(:user) }
let_it_be(:issue) { create(:issue) }
let_it_be(:chat_name) { create(:chat_name, user: user) }
let_it_be(:project) { issue.project }
let_it_be(:other_project) { create(:project, namespace: project.namespace) }
before do
[project, other_project].each { |prj| prj.add_maintainer(user) }
end
subject { described_class.new(project, chat_name) }
def process_message(message)
subject.execute(described_class.match(message))
end
context 'when the user can move the issue' do
context 'when the move fails' do
it 'returns the error message' do
message = "issue move #{issue.iid} #{project.full_path}"
expect(process_message(message)).to include(response_type: :ephemeral,
text: a_string_matching('Cannot move issue'))
end
end
context 'when the move succeeds' do
let(:message) { "issue move #{issue.iid} #{other_project.full_path}" }
it 'moves the issue to the new destination' do
expect { process_message(message) }.to change { Issue.count }.by(1)
new_issue = issue.reload.moved_to
expect(new_issue.state).to eq('opened')
expect(new_issue.project_id).to eq(other_project.id)
expect(new_issue.author_id).to eq(issue.author_id)
expect(issue.state).to eq('closed')
expect(issue.project_id).to eq(project.id)
end
it 'returns the new issue' do
expect(process_message(message))
.to include(response_type: :in_channel,
attachments: [a_hash_including(title_link: a_string_including(other_project.full_path))])
end
it 'mentions the old issue' do
expect(process_message(message))
.to include(attachments: [a_hash_including(pretext: a_string_including(project.full_path))])
end
end
end
context 'when the issue does not exist' do
it 'returns not found' do
message = "issue move #{issue.iid.succ} #{other_project.full_path}"
expect(process_message(message)).to include(response_type: :ephemeral,
text: a_string_matching('not found'))
end
end
context 'when the target project does not exist' do
it 'returns not found' do
message = "issue move #{issue.iid} #{other_project.full_path}/foo"
expect(process_message(message)).to include(response_type: :ephemeral,
text: a_string_matching('not found'))
end
end
context 'when the user cannot see the target project' do
it 'returns not found' do
message = "issue move #{issue.iid} #{other_project.full_path}"
other_project.team.truncate
expect(process_message(message)).to include(response_type: :ephemeral,
text: a_string_matching('not found'))
end
end
context 'when the user does not have the required permissions on the target project' do
it 'returns the error message' do
message = "issue move #{issue.iid} #{other_project.full_path}"
other_project.team.truncate
other_project.team.add_guest(user)
expect(process_message(message)).to include(response_type: :ephemeral,
text: a_string_matching('Cannot move issue'))
end
end
end
end
|