git_helper 1.3.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,233 @@
1
+ require_relative '../../lib/git_helper/merge_request.rb'
2
+
3
+ describe GitHelper::GitLabMergeRequest do
4
+ let(:local_code) { double(:local_code, read_template: 'template') }
5
+ let(:highline_cli) { double(:highline_cli) }
6
+ let(:gitlab_client_client) { double(:gitlab_client_client, project: :project, merge_request: :merge_request, create_merge_request: :created) }
7
+ let(:gitlab_client) { double(:gitlab_client, client: gitlab_client_client) }
8
+ let(:options) do
9
+ {
10
+ local_project: 'emmasax4/git_helper',
11
+ local_branch: 'main',
12
+ local_code: local_code,
13
+ cli: highline_cli
14
+ }
15
+ end
16
+
17
+ subject { GitHelper::GitLabMergeRequest.new(options) }
18
+
19
+ before do
20
+ allow(GitHelper::GitLabClient).to receive(:new).and_return(gitlab_client)
21
+ end
22
+
23
+ describe '#create' do
24
+ it 'should call the gitlab client to create' do
25
+ allow(subject).to receive(:squash_merge_request).and_return(true)
26
+ allow(subject).to receive(:remove_source_branch).and_return(false)
27
+ allow(subject).to receive(:new_mr_body).and_return('')
28
+ expect(gitlab_client_client).to receive(:create_merge_request)
29
+ subject.create({base_branch: 'base', new_title: 'title'})
30
+ end
31
+
32
+ it 'should call various other methods' do
33
+ expect(subject).to receive(:squash_merge_request).and_return(true)
34
+ expect(subject).to receive(:remove_source_branch).and_return(false)
35
+ expect(subject).to receive(:new_mr_body).and_return('')
36
+ allow(gitlab_client_client).to receive(:create_merge_request)
37
+ subject.create({base_branch: 'base', new_title: 'title'})
38
+ end
39
+
40
+ it 'should catch the raised error if the creation does not work' do
41
+ allow(subject).to receive(:squash_merge_request).and_return(true)
42
+ allow(subject).to receive(:remove_source_branch).and_return(false)
43
+ allow(subject).to receive(:new_mr_body).and_return('')
44
+ allow(gitlab_client_client).to receive(:create_merge_request).and_raise(StandardError)
45
+ expect(subject.create({base_branch: 'base', new_title: 'title'})).to eq(nil)
46
+ end
47
+ end
48
+
49
+ describe '#merge' do
50
+ it 'should call the gitlab client to merge' do
51
+ allow(subject).to receive(:existing_mr).and_return(double(should_remove_source_branch: true, squash: false, title: 'title'))
52
+ allow(subject).to receive(:mr_id).and_return(123)
53
+ expect(gitlab_client_client).to receive(:accept_merge_request)
54
+ subject.merge
55
+ end
56
+
57
+ it 'should call various other methods' do
58
+ expect(subject).to receive(:existing_mr).and_return(double(should_remove_source_branch: true, squash: false, title: 'title')).at_least(:once)
59
+ expect(subject).to receive(:mr_id).and_return(123).at_least(:once)
60
+ allow(gitlab_client_client).to receive(:accept_merge_request)
61
+ subject.merge
62
+ end
63
+
64
+ it 'should catch the raised error if the merge does not work' do
65
+ allow(subject).to receive(:existing_mr).and_return(double(should_remove_source_branch: true, squash: false, title: 'title'))
66
+ allow(subject).to receive(:mr_id).and_return(123)
67
+ allow(gitlab_client_client).to receive(:accept_merge_request).and_raise(StandardError)
68
+ expect(subject.merge).to eq(nil)
69
+ end
70
+
71
+ it 'should try to merge multiple times if the first merge errors' do
72
+ allow(subject).to receive(:existing_mr).and_return(double(should_remove_source_branch: true, squash: false, title: 'title'))
73
+ allow(subject).to receive(:mr_id).and_return(123)
74
+ expect(gitlab_client_client).to receive(:accept_merge_request).and_return(double(merge_commit_sha: nil)).exactly(2).times
75
+ expect(subject.merge).to eq(nil)
76
+ end
77
+ end
78
+
79
+ describe '#new_mr_body' do
80
+ it 'should call the local code if the template to apply exists' do
81
+ allow(subject).to receive(:template_name_to_apply).and_return('')
82
+ expect(local_code).to receive(:read_template)
83
+ subject.send(:new_mr_body)
84
+ end
85
+
86
+ it 'should not call the local code if the template is nil' do
87
+ allow(subject).to receive(:template_name_to_apply).and_return(nil)
88
+ expect(local_code).not_to receive(:read_template)
89
+ subject.send(:new_mr_body)
90
+ end
91
+
92
+ it 'should return an empty string if the template is nil' do
93
+ allow(subject).to receive(:template_name_to_apply).and_return(nil)
94
+ expect(subject.send(:new_mr_body)).to eq('')
95
+ end
96
+ end
97
+
98
+ describe '#template_name_to_apply' do
99
+ context 'if MR template options are empty' do
100
+ it 'should return nil' do
101
+ allow(subject).to receive(:mr_template_options).and_return([])
102
+ expect(subject.send(:template_name_to_apply)).to eq(nil)
103
+ end
104
+ end
105
+
106
+ context 'if there is one template option' do
107
+ it 'should call the CLI to ask about a single template' do
108
+ allow(subject).to receive(:mr_template_options).and_return(['template1'])
109
+ expect(highline_cli).to receive(:apply_template?).and_return(true)
110
+ subject.send(:template_name_to_apply)
111
+ end
112
+
113
+ it 'should return the single template if the user says yes' do
114
+ allow(subject).to receive(:mr_template_options).and_return(['template1'])
115
+ allow(highline_cli).to receive(:apply_template?).and_return(true)
116
+ expect(subject.send(:template_name_to_apply)).to eq('template1')
117
+ end
118
+
119
+ it 'should return nil if the user says no' do
120
+ allow(subject).to receive(:mr_template_options).and_return(['template1'])
121
+ allow(highline_cli).to receive(:apply_template?).and_return(false)
122
+ expect(subject.send(:template_name_to_apply)).to eq(nil)
123
+ end
124
+ end
125
+
126
+ context 'if there are multiple template options' do
127
+ it 'should call the CLI to ask which of multiple templates to apply' do
128
+ allow(subject).to receive(:mr_template_options).and_return(['template1', 'template2'])
129
+ expect(highline_cli).to receive(:template_to_apply).and_return('template1')
130
+ subject.send(:template_name_to_apply)
131
+ end
132
+
133
+ it 'should return the answer template if the user says yes' do
134
+ allow(subject).to receive(:mr_template_options).and_return(['template1', 'template2'])
135
+ allow(highline_cli).to receive(:template_to_apply).and_return('template1')
136
+ expect(subject.send(:template_name_to_apply)).to eq('template1')
137
+ end
138
+
139
+ it 'should return nil if the user says no' do
140
+ allow(subject).to receive(:mr_template_options).and_return(['template1', 'template2'])
141
+ allow(highline_cli).to receive(:template_to_apply).and_return('None')
142
+ expect(subject.send(:template_name_to_apply)).to eq(nil)
143
+ end
144
+ end
145
+ end
146
+
147
+ describe '#mr_template_options' do
148
+ it 'should call the local code' do
149
+ expect(local_code).to receive(:template_options)
150
+ subject.send(:mr_template_options)
151
+ end
152
+ end
153
+
154
+ describe '#mr_id' do
155
+ it 'should ask the CLI for the code request ID' do
156
+ expect(highline_cli).to receive(:code_request_id).and_return(123)
157
+ subject.send(:mr_id)
158
+ end
159
+
160
+ it 'should equal an integer' do
161
+ expect(highline_cli).to receive(:code_request_id).and_return(123)
162
+ expect(subject.send(:mr_id)).to eq(123)
163
+ end
164
+ end
165
+
166
+ describe '#squash_merge_request' do
167
+ it 'should ask the CLI for the code request ID' do
168
+ expect(highline_cli).to receive(:squash_merge_request?).and_return(true)
169
+ subject.send(:squash_merge_request)
170
+ end
171
+
172
+ it 'should be a boolean' do
173
+ expect(highline_cli).to receive(:squash_merge_request?).and_return(false)
174
+ expect([true, false]).to include(subject.send(:squash_merge_request))
175
+ end
176
+ end
177
+
178
+ describe '#remove_source_branch' do
179
+ before do
180
+ allow(subject).to receive(:existing_project).and_return(double(remove_source_branch_after_merge: nil))
181
+ end
182
+
183
+ context 'when the existing project has no setting' do
184
+ it 'should ask the CLI for the code request ID' do
185
+ expect(highline_cli).to receive(:remove_source_branch?).and_return(true)
186
+ subject.send(:remove_source_branch)
187
+ end
188
+
189
+ it 'should be a boolean' do
190
+ allow(highline_cli).to receive(:remove_source_branch?).and_return(false)
191
+ expect([true, false]).to include(subject.send(:remove_source_branch))
192
+ end
193
+ end
194
+
195
+ it 'should ask the existing project' do
196
+ expect(subject).to receive(:existing_project).and_return(double(remove_source_branch_after_merge: true))
197
+ subject.send(:remove_source_branch)
198
+ end
199
+
200
+ it "should return the existing project's setting if it exists" do
201
+ allow(subject).to receive(:existing_project).and_return(double(remove_source_branch_after_merge: true))
202
+ expect(subject.send(:remove_source_branch)).to eq(true)
203
+ end
204
+
205
+ it "should return the existing project's setting if it exists" do
206
+ allow(subject).to receive(:existing_project).and_return(double(remove_source_branch_after_merge: false))
207
+ allow(highline_cli).to receive(:remove_source_branch?).and_return(true)
208
+ expect(subject.send(:remove_source_branch)).to eq(true)
209
+ end
210
+ end
211
+
212
+ describe '#existing_project' do
213
+ it 'should call the gitlab client' do
214
+ expect(gitlab_client_client).to receive(:project).and_return(:project)
215
+ subject.send(:existing_project)
216
+ end
217
+ end
218
+
219
+ describe '#existing_mr' do
220
+ it 'should call the gitlab client' do
221
+ allow(highline_cli).to receive(:code_request_id).and_return(123)
222
+ expect(gitlab_client_client).to receive(:merge_request).and_return(:merge_request)
223
+ subject.send(:existing_mr)
224
+ end
225
+ end
226
+
227
+ describe '#gitlab_client' do
228
+ it 'should call the gitlab client' do
229
+ expect(GitHelper::GitLabClient).to receive(:new).and_return(gitlab_client)
230
+ subject.send(:gitlab_client)
231
+ end
232
+ end
233
+ end
@@ -0,0 +1,43 @@
1
+ require_relative '../../lib/git_helper/new_branch.rb'
2
+
3
+ describe GitHelper::NewBranch do
4
+ let(:new_branch_name) { 'new-branch-name' }
5
+ let(:local_code) { double(:local_code, new_branch: :commit) }
6
+ let(:cli) { double(:highline_cli, new_branch_name: new_branch_name) }
7
+
8
+ subject { GitHelper::NewBranch.new }
9
+
10
+ before do
11
+ allow(GitHelper::LocalCode).to receive(:new).and_return(local_code)
12
+ allow(GitHelper::HighlineCli).to receive(:new).and_return(cli)
13
+ end
14
+
15
+ it 'should call GitHelper::LocalCode' do
16
+ expect(GitHelper::LocalCode).to receive(:new).and_return(local_code)
17
+ subject.execute
18
+ end
19
+
20
+ it 'should call the new_branch method from the local code class' do
21
+ expect(local_code).to receive(:new_branch)
22
+ subject.execute
23
+ end
24
+
25
+ context 'when no branch name is passed in' do
26
+ it 'should call the highline cli' do
27
+ expect(GitHelper::HighlineCli).to receive(:new).and_return(cli)
28
+ subject.execute
29
+ end
30
+
31
+ it 'should ask the highline cli what the new branch name should be' do
32
+ expect(cli).to receive(:new_branch_name)
33
+ subject.execute
34
+ end
35
+ end
36
+
37
+ context 'when there is a branch name passed in' do
38
+ it 'should not create a highline cli' do
39
+ expect(GitHelper::HighlineCli).not_to receive(:new)
40
+ subject.execute(new_branch_name)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,25 @@
1
+ require_relative '../../lib/git_helper/octokit_client.rb'
2
+
3
+ describe GitHelper::OctokitClient do
4
+ let(:git_config_reader) { double(:git_config_reader, github_token: :token) }
5
+
6
+ subject { GitHelper::OctokitClient.new }
7
+
8
+ before do
9
+ allow(GitHelper::GitConfigReader).to receive(:new).and_return(git_config_reader)
10
+ end
11
+
12
+ describe '#client' do
13
+ it 'should call the GitLab client to make a new client' do
14
+ expect(Octokit::Client).to receive(:new)
15
+ subject.client
16
+ end
17
+ end
18
+
19
+ describe '#git_config_reader' do
20
+ it 'should make a new git config reader' do
21
+ expect(GitHelper::GitConfigReader).to receive(:new)
22
+ subject.send(:git_config_reader)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,245 @@
1
+ require_relative '../../lib/git_helper/pull_request.rb'
2
+
3
+ describe GitHelper::GitHubPullRequest do
4
+ let(:local_code) { double(:local_code, read_template: 'template') }
5
+ let(:highline_cli) { double(:highline_cli) }
6
+ let(:octokit_client_client) { double(:octokit_client_client, project: :project, merge_request: :merge_request, create_merge_request: :created) }
7
+ let(:octokit_client) { double(:octokit_client, client: octokit_client_client) }
8
+ let(:options) do
9
+ {
10
+ local_project: 'emmasax4/git_helper',
11
+ local_branch: 'main',
12
+ local_code: local_code,
13
+ cli: highline_cli
14
+ }
15
+ end
16
+
17
+ subject { GitHelper::GitHubPullRequest.new(options) }
18
+
19
+ before do
20
+ allow(GitHelper::OctokitClient).to receive(:new).and_return(octokit_client)
21
+ end
22
+
23
+ describe '#create' do
24
+ it 'should call the octokit client to create' do
25
+ allow(subject).to receive(:new_pr_body).and_return('')
26
+ expect(octokit_client_client).to receive(:create_pull_request)
27
+ subject.create({base_branch: 'base', new_title: 'title'})
28
+ end
29
+
30
+ it 'should call various other methods' do
31
+ expect(subject).to receive(:new_pr_body).and_return('').at_least(:once)
32
+ allow(octokit_client_client).to receive(:create_pull_request)
33
+ subject.create({base_branch: 'base', new_title: 'title'})
34
+ end
35
+
36
+ it 'should catch the raised error if the creation does not work' do
37
+ allow(subject).to receive(:new_pr_body).and_return('')
38
+ allow(octokit_client_client).to receive(:create_pull_request).and_raise(StandardError)
39
+ expect(subject.create({base_branch: 'base', new_title: 'title'})).to eq(nil)
40
+ end
41
+ end
42
+
43
+ describe '#merge' do
44
+ it 'should call the octokit client to merge' do
45
+ allow(subject).to receive(:existing_pr).and_return(double(title: 'title'))
46
+ allow(subject).to receive(:merge_method).and_return('rebase')
47
+ allow(subject).to receive(:pr_id).and_return(123)
48
+ expect(octokit_client_client).to receive(:merge_pull_request)
49
+ subject.merge
50
+ end
51
+
52
+ it 'should call various other methods' do
53
+ expect(subject).to receive(:existing_pr).and_return(double(title: 'title')).at_least(:once)
54
+ expect(subject).to receive(:merge_method).and_return('rebase').at_least(:once)
55
+ expect(subject).to receive(:pr_id).and_return(123).at_least(:once)
56
+ allow(octokit_client_client).to receive(:merge_pull_request)
57
+ subject.merge
58
+ end
59
+
60
+ it 'should catch the raised error if the merge does not work' do
61
+ allow(subject).to receive(:existing_pr).and_return(double(title: 'title'))
62
+ allow(subject).to receive(:merge_method).and_return('rebase')
63
+ allow(subject).to receive(:pr_id).and_return(123)
64
+ allow(octokit_client_client).to receive(:merge_pull_request).and_raise(StandardError)
65
+ expect(subject.merge).to eq(nil)
66
+ end
67
+ end
68
+
69
+ describe '#new_pr_body' do
70
+ it 'should call the local code if the template to apply exists' do
71
+ allow(subject).to receive(:template_name_to_apply).and_return('')
72
+ expect(local_code).to receive(:read_template)
73
+ subject.send(:new_pr_body)
74
+ end
75
+
76
+ it 'should not call the local code if the template is nil' do
77
+ allow(subject).to receive(:template_name_to_apply).and_return(nil)
78
+ expect(local_code).not_to receive(:read_template)
79
+ subject.send(:new_pr_body)
80
+ end
81
+
82
+ it 'should return an empty string if the template is nil' do
83
+ allow(subject).to receive(:template_name_to_apply).and_return(nil)
84
+ expect(subject.send(:new_pr_body)).to eq('')
85
+ end
86
+ end
87
+
88
+ describe '#template_name_to_apply' do
89
+ context 'if PR template options are empty' do
90
+ it 'should return nil' do
91
+ allow(subject).to receive(:pr_template_options).and_return([])
92
+ expect(subject.send(:template_name_to_apply)).to eq(nil)
93
+ end
94
+ end
95
+
96
+ context 'if there is one template option' do
97
+ it 'should call the CLI to ask about a single template' do
98
+ allow(subject).to receive(:pr_template_options).and_return(['template1'])
99
+ expect(highline_cli).to receive(:apply_template?).and_return(true)
100
+ subject.send(:template_name_to_apply)
101
+ end
102
+
103
+ it 'should return the single template if the user says yes' do
104
+ allow(subject).to receive(:pr_template_options).and_return(['template1'])
105
+ allow(highline_cli).to receive(:apply_template?).and_return(true)
106
+ expect(subject.send(:template_name_to_apply)).to eq('template1')
107
+ end
108
+
109
+ it 'should return nil if the user says no' do
110
+ allow(subject).to receive(:pr_template_options).and_return(['template1'])
111
+ allow(highline_cli).to receive(:apply_template?).and_return(false)
112
+ expect(subject.send(:template_name_to_apply)).to eq(nil)
113
+ end
114
+ end
115
+
116
+ context 'if there are multiple template options' do
117
+ it 'should call the CLI to ask which of multiple templates to apply' do
118
+ allow(subject).to receive(:pr_template_options).and_return(['template1', 'template2'])
119
+ expect(highline_cli).to receive(:template_to_apply).and_return('template1')
120
+ subject.send(:template_name_to_apply)
121
+ end
122
+
123
+ it 'should return the answer template if the user says yes' do
124
+ allow(subject).to receive(:pr_template_options).and_return(['template1', 'template2'])
125
+ allow(highline_cli).to receive(:template_to_apply).and_return('template1')
126
+ expect(subject.send(:template_name_to_apply)).to eq('template1')
127
+ end
128
+
129
+ it 'should return nil if the user says no' do
130
+ allow(subject).to receive(:pr_template_options).and_return(['template1', 'template2'])
131
+ allow(highline_cli).to receive(:template_to_apply).and_return('None')
132
+ expect(subject.send(:template_name_to_apply)).to eq(nil)
133
+ end
134
+ end
135
+ end
136
+
137
+ describe '#pr_template_options' do
138
+ it 'should call the local code' do
139
+ expect(local_code).to receive(:template_options)
140
+ subject.send(:pr_template_options)
141
+ end
142
+ end
143
+
144
+ describe '#pr_id' do
145
+ it 'should ask the CLI for the code request ID' do
146
+ expect(highline_cli).to receive(:code_request_id).and_return(123)
147
+ subject.send(:pr_id)
148
+ end
149
+
150
+ it 'should equal an integer' do
151
+ expect(highline_cli).to receive(:code_request_id).and_return(123)
152
+ expect(subject.send(:pr_id)).to eq(123)
153
+ end
154
+ end
155
+
156
+ describe '#merge_method' do
157
+ let(:project) { double(:project, allow_merge_commit: true, allow_squash_merge: true, allow_rebase_merge: true) }
158
+
159
+ before do
160
+ allow(subject).to receive(:existing_project).and_return(project)
161
+ allow(highline_cli).to receive(:merge_method)
162
+ end
163
+
164
+ it 'should ask the CLI for the merge_method' do
165
+ expect(highline_cli).to receive(:merge_method).and_return('merge')
166
+ subject.send(:merge_method)
167
+ end
168
+
169
+ it 'should be a string' do
170
+ allow(highline_cli).to receive(:merge_method).and_return('merge')
171
+ expect(subject.send(:merge_method)).to be_a(String)
172
+ end
173
+
174
+ context "if there's only one item" do
175
+ let(:project) { double(:project, allow_merge_commit: true, allow_squash_merge: false, allow_rebase_merge: false) }
176
+
177
+ it 'should not ask the CLI anything' do
178
+ expect(highline_cli).not_to receive(:merge_method)
179
+ subject.send(:merge_method)
180
+ end
181
+ end
182
+ end
183
+
184
+ describe '#merge_options' do
185
+ let(:project) { double(:project, allow_merge_commit: true, allow_squash_merge: true, allow_rebase_merge: true) }
186
+
187
+ before do
188
+ allow(subject).to receive(:existing_project).and_return(project)
189
+ end
190
+
191
+ it 'should return an array' do
192
+ expect(subject.send(:merge_options)).to be_a(Array)
193
+ end
194
+
195
+ it 'should have three items' do
196
+ expect(subject.send(:merge_options).length).to eq(3)
197
+ end
198
+
199
+ context 'when two options are present' do
200
+ let(:project) { double(:project, allow_merge_commit: false, allow_squash_merge: true, allow_rebase_merge: true) }
201
+
202
+ it 'should have two items' do
203
+ expect(subject.send(:merge_options).length).to eq(2)
204
+ end
205
+ end
206
+
207
+ context 'when one option is present' do
208
+ let(:project) { double(:project, allow_merge_commit: false, allow_squash_merge: false, allow_rebase_merge: true) }
209
+
210
+ it 'should have one item' do
211
+ expect(subject.send(:merge_options).length).to eq(1)
212
+ end
213
+ end
214
+
215
+ context 'when no options are present' do
216
+ let(:project) { double(:project, allow_merge_commit: false, allow_squash_merge: false, allow_rebase_merge: false) }
217
+
218
+ it 'should have no items' do
219
+ expect(subject.send(:merge_options).length).to eq(0)
220
+ end
221
+ end
222
+ end
223
+
224
+ describe '#existing_project' do
225
+ it 'should call the octokit client' do
226
+ expect(octokit_client_client).to receive(:repository).and_return(:repository)
227
+ subject.send(:existing_project)
228
+ end
229
+ end
230
+
231
+ describe '#existing_pr' do
232
+ it 'should call the octokit client' do
233
+ allow(highline_cli).to receive(:code_request_id).and_return(123)
234
+ expect(octokit_client_client).to receive(:pull_request).and_return(:pull_request)
235
+ subject.send(:existing_pr)
236
+ end
237
+ end
238
+
239
+ describe '#octokit_client' do
240
+ it 'should call the octokit client' do
241
+ expect(GitHelper::OctokitClient).to receive(:new).and_return(octokit_client)
242
+ subject.send(:octokit_client)
243
+ end
244
+ end
245
+ end