git_reflow 0.8.6 → 0.8.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (77) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +348 -348
  4. data/Gemfile.lock +13 -15
  5. data/LICENSE +20 -20
  6. data/README.rdoc +461 -461
  7. data/Rakefile +8 -8
  8. data/bin/console +7 -7
  9. data/bin/setup +6 -6
  10. data/circle.yml +5 -5
  11. data/exe/git-reflow +36 -36
  12. data/git_reflow.gemspec +1 -1
  13. data/lib/git_reflow/commands/deliver.rb +10 -10
  14. data/lib/git_reflow/commands/refresh.rb +20 -20
  15. data/lib/git_reflow/commands/review.rb +13 -13
  16. data/lib/git_reflow/commands/setup.rb +11 -11
  17. data/lib/git_reflow/commands/stage.rb +9 -9
  18. data/lib/git_reflow/commands/start.rb +22 -22
  19. data/lib/git_reflow/commands/status.rb +7 -7
  20. data/lib/git_reflow/config.rb +9 -9
  21. data/lib/git_reflow/git_server/base.rb +68 -68
  22. data/lib/git_reflow/git_server/bit_bucket/pull_request.rb +84 -84
  23. data/lib/git_reflow/git_server/bit_bucket.rb +101 -101
  24. data/lib/git_reflow/git_server/git_hub/pull_request.rb +4 -1
  25. data/lib/git_reflow/git_server/pull_request.rb +11 -2
  26. data/lib/git_reflow/git_server.rb +63 -63
  27. data/lib/git_reflow/logger.rb +49 -0
  28. data/lib/git_reflow/merge_error.rb +9 -9
  29. data/lib/git_reflow/os_detector.rb +23 -23
  30. data/lib/git_reflow/rspec/command_line_helpers.rb +12 -8
  31. data/lib/git_reflow/rspec/stub_helpers.rb +13 -13
  32. data/lib/git_reflow/rspec.rb +2 -2
  33. data/lib/git_reflow/sandbox.rb +11 -6
  34. data/lib/git_reflow/version.rb +1 -1
  35. data/lib/git_reflow/workflow.rb +59 -59
  36. data/lib/git_reflow/workflows/core.rb +238 -238
  37. data/lib/git_reflow/workflows/flat_merge.rb +10 -10
  38. data/lib/git_reflow.rb +11 -0
  39. data/spec/fixtures/awesome_workflow.rb +7 -0
  40. data/spec/fixtures/git/git_config +7 -0
  41. data/spec/fixtures/issues/comment.json.erb +27 -0
  42. data/spec/fixtures/issues/comments.json +29 -0
  43. data/spec/fixtures/issues/comments.json.erb +15 -0
  44. data/spec/fixtures/pull_requests/comment.json.erb +45 -0
  45. data/spec/fixtures/pull_requests/comments.json +47 -0
  46. data/spec/fixtures/pull_requests/comments.json.erb +15 -0
  47. data/spec/fixtures/pull_requests/commits.json +29 -0
  48. data/spec/fixtures/pull_requests/external_pull_request.json +145 -0
  49. data/spec/fixtures/pull_requests/pull_request.json +142 -0
  50. data/spec/fixtures/pull_requests/pull_request.json.erb +142 -0
  51. data/spec/fixtures/pull_requests/pull_request_exists_error.json +32 -0
  52. data/spec/fixtures/pull_requests/pull_requests.json +136 -0
  53. data/spec/fixtures/repositories/commit.json +53 -0
  54. data/spec/fixtures/repositories/commit.json.erb +53 -0
  55. data/spec/fixtures/repositories/commits.json.erb +13 -0
  56. data/spec/fixtures/repositories/statuses.json +31 -0
  57. data/spec/fixtures/workflow_with_super.rb +8 -0
  58. data/spec/lib/git_reflow/config_spec.rb +74 -0
  59. data/spec/lib/git_reflow/git_helpers_spec.rb +182 -0
  60. data/spec/lib/git_reflow/git_server/bit_bucket_spec.rb +81 -0
  61. data/spec/lib/git_reflow/git_server/git_hub/pull_request_spec.rb +587 -0
  62. data/spec/lib/git_reflow/git_server/git_hub_spec.rb +221 -0
  63. data/spec/lib/git_reflow/git_server/pull_request_spec.rb +524 -0
  64. data/spec/lib/git_reflow/git_server_spec.rb +101 -0
  65. data/spec/lib/git_reflow/logger_spec.rb +18 -0
  66. data/spec/lib/git_reflow/sandbox_spec.rb +15 -0
  67. data/spec/lib/git_reflow/workflow_spec.rb +59 -0
  68. data/spec/lib/git_reflow/workflows/core_spec.rb +665 -0
  69. data/spec/lib/git_reflow/workflows/flat_merge_spec.rb +59 -0
  70. data/spec/lib/git_reflow_spec.rb +75 -0
  71. data/spec/spec_helper.rb +38 -0
  72. data/spec/support/fake_github.rb +128 -0
  73. data/spec/support/fixtures.rb +54 -0
  74. data/spec/support/github_helpers.rb +109 -0
  75. data/spec/support/mock_pull_request.rb +17 -0
  76. data/spec/support/web_mocks.rb +39 -0
  77. metadata +83 -6
@@ -0,0 +1,587 @@
1
+ require 'spec_helper'
2
+
3
+ describe GitReflow::GitServer::GitHub::PullRequest do
4
+ let(:user) { 'reenhanced' }
5
+ let(:password) { 'shazam' }
6
+ let(:repo) { 'repo' }
7
+ let(:oauth_token_hash) { Hashie::Mash.new({ token: 'a1b2c3d4e5f6g7h8i9j0'}) }
8
+ let(:hostname) { 'hostname.local' }
9
+ let(:github_site) { 'https://github.com' }
10
+ let(:github_api_endpoint) { 'https://api.github.com' }
11
+ let(:enterprise_site) { 'https://github.gittyup.com' }
12
+ let(:enterprise_api) { 'https://github.gittyup.com/api/v3' }
13
+ let(:github) { stub_github_with }
14
+ let!(:github_api) { github.connection }
15
+ let(:existing_pull_request) { Fixture.new('pull_requests/external_pull_request.json').to_json_hashie }
16
+ let(:existing_pull_requests) { Fixture.new('pull_requests/pull_requests.json').to_json_hashie }
17
+ let(:existing_pull_commits) { Fixture.new('pull_requests/commits.json').to_json_hashie }
18
+ let(:comment_author) { 'octocat' }
19
+ let(:feature_branch_name) { existing_pull_request.head.label[/[^:]+$/] }
20
+ let(:base_branch_name) { existing_pull_request.base.label[/[^:]+$/] }
21
+ let(:existing_pull_comments) {
22
+ Fixture.new('pull_requests/comments.json.erb',
23
+ repo_owner: user,
24
+ repo_name: repo,
25
+ comments: [{author: comment_author}],
26
+ pull_request_number: existing_pull_request.number).to_json_hashie }
27
+ let(:existing_issue_comments) {
28
+ Fixture.new('issues/comments.json.erb',
29
+ repo_owner: user,
30
+ repo_name: repo,
31
+ comments: [{author: comment_author}],
32
+ pull_request_number: existing_pull_request.number).to_json_hashie }
33
+
34
+ let(:pr) { GitReflow::GitServer::GitHub::PullRequest.new(existing_pull_request) }
35
+
36
+
37
+ before do
38
+ stub_command_line_inputs({
39
+ "Please enter your GitHub username: " => user,
40
+ "Please enter your GitHub password (we do NOT store this): " => password,
41
+ "Please enter your Enterprise site URL (e.g. https://github.company.com):" => enterprise_site,
42
+ "Please enter your Enterprise API endpoint (e.g. https://github.company.com/api/v3):" => enterprise_api
43
+ })
44
+
45
+ allow(github.class).to receive(:remote_user).and_return(user)
46
+ allow(github.class).to receive(:remote_repo_name).and_return(repo)
47
+ allow(GitReflow::GitServer::PullRequest).to receive(:approval_regex).and_return(/(?i-mx:lgtm|looks good to me|:\+1:|:thumbsup:|:shipit:)/)
48
+ end
49
+
50
+ describe '#initialize(options)' do
51
+ specify { expect(pr.number).to eql(existing_pull_request.number) }
52
+ specify { expect(pr.description).to eql(existing_pull_request.body) }
53
+ specify { expect(pr.html_url).to eql(existing_pull_request.html_url) }
54
+ specify { expect(pr.feature_branch_name).to eql(feature_branch_name) }
55
+ specify { expect(pr.base_branch_name).to eql(base_branch_name) }
56
+ specify { expect(pr.build_status).to eql('success') }
57
+ specify { expect(pr.source_object).to eql(existing_pull_request) }
58
+ end
59
+
60
+ describe '#commit_author' do
61
+ subject { pr.commit_author }
62
+
63
+ before do
64
+ stub_request(:get, %r{#{GitReflow.git_server.class.api_endpoint}/repos/#{user}/#{repo}/pulls/#{existing_pull_request.number}/commits}).
65
+ with(query: {"access_token" => "a1b2c3d4e5f6g7h8i9j0"}).
66
+ to_return(:body => Fixture.new("pull_requests/commits.json").to_s, status: 201, headers: {content_type: "application/json; charset=utf-8"})
67
+ end
68
+ specify { expect(subject).to eql("#{existing_pull_commits.first.commit.author.name} <#{existing_pull_commits.first.commit.author.email}>") }
69
+ end
70
+
71
+ describe '#comments' do
72
+ subject { pr.comments }
73
+
74
+ context "Testing Appending of Comments" do
75
+ before do
76
+ FakeGitHub.new(
77
+ repo_owner: user,
78
+ repo_name: repo,
79
+ pull_request: {
80
+ number: existing_pull_request.number,
81
+ comments: [{author: comment_author}]
82
+ },
83
+ issue: {
84
+ number: existing_pull_request.number,
85
+ comments: [{author: comment_author}]
86
+ })
87
+ end
88
+ specify { expect(subject).to eql(existing_pull_comments.to_a + existing_issue_comments.to_a) }
89
+ end
90
+
91
+ context "Testing Nil Comments" do
92
+ before do
93
+ stub_request(:get, "https://api.github.com/repos/reenhanced/repo/pulls/2/comments?access_token=a1b2c3d4e5f6g7h8i9j0").
94
+ with(:headers => {'Accept'=>'application/vnd.github.v3+json,application/vnd.github.beta+json;q=0.5,application/json;q=0.1', 'Accept-Charset'=>'utf-8', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Authorization'=>'token a1b2c3d4e5f6g7h8i9j0', 'User-Agent'=>'Github API Ruby Gem 0.15.0'}).
95
+ to_return(:status => 200, :body => "", :headers => {})
96
+
97
+ FakeGitHub.new(
98
+ repo_owner: user,
99
+ repo_name: repo,
100
+ pull_request: {
101
+ number: existing_pull_request.number,
102
+ comments: nil
103
+ },
104
+ issue: {
105
+ number: existing_pull_request.number,
106
+ comments: nil
107
+ })
108
+ end
109
+ specify { expect(subject).to eql([]) }
110
+ end
111
+ end
112
+
113
+ describe '#reviewers' do
114
+ subject { pr.reviewers }
115
+
116
+ before do
117
+ allow(existing_pull_request.user).to receive(:login).and_return('ringo')
118
+
119
+ FakeGitHub.new(
120
+ repo_owner: user,
121
+ repo_name: repo,
122
+ pull_request: {
123
+ number: existing_pull_request.number,
124
+ owner: existing_pull_request.user.login,
125
+ comments: [{author: 'tito'}, {author: 'bobby'}, {author: 'ringo'}]
126
+ },
127
+ issue: {
128
+ number: existing_pull_request.number,
129
+ comments: [{author: 'ringo'}, {author: 'randy'}]
130
+ })
131
+ end
132
+
133
+ specify { expect(subject).to eq(['tito', 'bobby', 'randy']) }
134
+ end
135
+
136
+
137
+ describe "#approved?" do
138
+ subject { pr.approved? }
139
+
140
+ context "no approvals and build success" do
141
+ before do
142
+ FakeGitHub.new(
143
+ repo_owner: user,
144
+ repo_name: repo,
145
+ pull_request: {
146
+ number: existing_pull_request.number,
147
+ owner: existing_pull_request.head.user.login,
148
+ comments: []
149
+ })
150
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:minimum_approvals).and_return("0")
151
+ end
152
+ specify { expect(subject).to be_truthy }
153
+ end
154
+
155
+ context "all commenters must approve and minimum_approvals is nil" do
156
+ before do
157
+ FakeGitHub.new(
158
+ repo_owner: user,
159
+ repo_name: repo,
160
+ pull_request: {
161
+ number: existing_pull_request.number,
162
+ owner: existing_pull_request.head.user.login,
163
+ comments: []
164
+ })
165
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:minimum_approvals).and_return(nil)
166
+ allow(pr).to receive(:has_comments?).and_return(true)
167
+ allow(pr).to receive(:approvals).and_return(["Simon"])
168
+ allow(pr).to receive(:reviewers_pending_response).and_return([])
169
+ end
170
+ specify { expect(subject).to be_truthy }
171
+ end
172
+
173
+ context "all commenters must approve but we have no pending reviewers" do
174
+ before do
175
+ FakeGitHub.new(
176
+ repo_owner: user,
177
+ repo_name: repo,
178
+ pull_request: {
179
+ number: existing_pull_request.number,
180
+ owner: existing_pull_request.head.user.login,
181
+ comments: []
182
+ })
183
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:minimum_approvals).and_return("")
184
+ allow(pr).to receive(:has_comments?).and_return(true)
185
+ allow(pr).to receive(:approvals).and_return(["Simon"])
186
+ allow(pr).to receive(:reviewers_pending_response).and_return([])
187
+ end
188
+ specify { expect(subject).to be_truthy }
189
+ end
190
+
191
+ context "all commenters must approve but we have 1 pending reviewer" do
192
+ before do
193
+ FakeGitHub.new(
194
+ repo_owner: user,
195
+ repo_name: repo,
196
+ pull_request: {
197
+ number: existing_pull_request.number,
198
+ owner: existing_pull_request.head.user.login,
199
+ comments: []
200
+ })
201
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:minimum_approvals).and_return("")
202
+ allow(pr).to receive(:has_comments?).and_return(true)
203
+ allow(pr).to receive(:approvals).and_return(["Simon"])
204
+ allow(pr).to receive(:reviewers_pending_response).and_return(["Simon"])
205
+ end
206
+ specify { expect(subject).to be_falsy }
207
+ end
208
+
209
+ context "2 approvals required but we only have 1 approval" do
210
+ before do
211
+ FakeGitHub.new(
212
+ repo_owner: user,
213
+ repo_name: repo,
214
+ pull_request: {
215
+ number: existing_pull_request.number,
216
+ owner: existing_pull_request.head.user.login,
217
+ comments: []
218
+ })
219
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:minimum_approvals).and_return("2")
220
+ allow(pr).to receive(:approvals).and_return(["Simon"])
221
+ allow(pr).to receive(:last_comment).and_return("LGTM")
222
+ end
223
+ specify { expect(subject).to be_falsy }
224
+ end
225
+
226
+ context "2 approvals required and we have 2 approvals but last comment is not approval" do
227
+ before do
228
+ FakeGitHub.new(
229
+ repo_owner: user,
230
+ repo_name: repo,
231
+ pull_request: {
232
+ number: existing_pull_request.number,
233
+ owner: existing_pull_request.head.user.login,
234
+ comments: []
235
+ })
236
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:minimum_approvals).and_return("2")
237
+ allow(pr).to receive(:approvals).and_return(["Simon", "Peter"])
238
+ allow(pr).to receive(:last_comment).and_return("Boo")
239
+ end
240
+ specify { expect(subject).to be_falsy }
241
+ end
242
+
243
+ context "2 approvals required and we have 2 approvals and last comment is approval" do
244
+ before do
245
+ FakeGitHub.new(
246
+ repo_owner: user,
247
+ repo_name: repo,
248
+ pull_request: {
249
+ number: existing_pull_request.number,
250
+ owner: existing_pull_request.head.user.login,
251
+ comments: []
252
+ })
253
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:minimum_approvals).and_return("2")
254
+ allow(pr).to receive(:approvals).and_return(["Simon", "Peter"])
255
+ allow(pr).to receive(:last_comment).and_return("LGTM")
256
+ end
257
+ specify { expect(subject).to be_truthy }
258
+ end
259
+ end
260
+
261
+ describe '#approvals' do
262
+ subject { pr.approvals }
263
+
264
+ context "no comments" do
265
+ before do
266
+ FakeGitHub.new(
267
+ repo_owner: user,
268
+ repo_name: repo,
269
+ pull_request: {
270
+ number: existing_pull_request.number,
271
+ owner: existing_pull_request.head.user.login,
272
+ comments: []
273
+ })
274
+ end
275
+
276
+ specify { expect(subject).to eq([]) }
277
+ end
278
+
279
+ context "single reviewer without approval" do
280
+ before do
281
+ FakeGitHub.new(
282
+ repo_owner: user,
283
+ repo_name: repo,
284
+ pull_request: {
285
+ number: existing_pull_request.number,
286
+ owner: existing_pull_request.head.user.login,
287
+ comments: [{author: 'tito', body: 'This is some funky stuff'}]
288
+ })
289
+ end
290
+
291
+ specify { expect(subject).to eq([]) }
292
+ end
293
+
294
+ context "single reviewer with approval" do
295
+ before do
296
+ FakeGitHub.new(
297
+ repo_owner: user,
298
+ repo_name: repo,
299
+ pull_request: {
300
+ number: existing_pull_request.number,
301
+ owner: existing_pull_request.head.user.login,
302
+ comments: [{author: 'tito', body: 'LGTM'}]
303
+ })
304
+ end
305
+
306
+ specify { expect(subject).to eq(['tito']) }
307
+
308
+ context "but a new commit has been introduced" do
309
+ before do
310
+ FakeGitHub.new(
311
+ repo_owner: user,
312
+ repo_name: repo,
313
+ commits: [
314
+ {
315
+ author: user,
316
+ pull_request_number: existing_pull_request.number,
317
+ created_at: Chronic.parse("1 second ago")
318
+ }
319
+ ],
320
+ pull_request: {
321
+ number: existing_pull_request.number,
322
+ owner: existing_pull_request.head.user.login,
323
+ comments: [{author: 'tito', body: 'LGTM', created_at: Chronic.parse('1 minute ago')}]
324
+ })
325
+ end
326
+
327
+ specify { expect(subject).to eq([]) }
328
+ end
329
+ end
330
+
331
+ context "multiple reviewers with only one approval" do
332
+ before do
333
+ FakeGitHub.new(
334
+ repo_owner: user,
335
+ repo_name: repo,
336
+ pull_request: {
337
+ number: existing_pull_request.number,
338
+ owner: existing_pull_request.head.user.login,
339
+ comments: [{author: 'tito', body: 'LGTM'}, {author: 'ringo', body: 'Needs more cowbell.'}]
340
+ })
341
+ end
342
+
343
+ specify { expect(subject).to eq(['tito']) }
344
+ end
345
+
346
+ context "multiple reviewers with all approvals" do
347
+ before do
348
+ FakeGitHub.new(
349
+ repo_owner: user,
350
+ repo_name: repo,
351
+ pull_request: {
352
+ number: existing_pull_request.number,
353
+ owner: existing_pull_request.head.user.login,
354
+ comments: [{author: 'tito', body: 'lgtm'}, {author: 'ringo', body: ':+1:'}]
355
+ })
356
+
357
+ allow(GitReflow::GitServer::GitHub::PullRequest).to receive(:approval_regex).and_return(/(?i-mx:lgtm|looks good to me|:\+1:|:thumbsup:|:shipit:)/)
358
+ end
359
+
360
+ context "2 approvals" do
361
+ specify { expect(subject).to eq(['tito', 'ringo']) }
362
+ end
363
+
364
+ context "but a new commit has been introduced" do
365
+ before do
366
+ FakeGitHub.new(
367
+ repo_owner: user,
368
+ repo_name: repo,
369
+ commits: [
370
+ {
371
+ author: user,
372
+ pull_request_number: existing_pull_request.number,
373
+ created_at: Chronic.parse("1 second ago")
374
+ }
375
+ ],
376
+ pull_request: {
377
+ number: existing_pull_request.number,
378
+ owner: existing_pull_request.head.user.login,
379
+ comments: [{author: 'tito', body: 'lgtm', created_at: Chronic.parse('1 minute ago')}, {author: 'ringo', body: ':+1:', created_at: Chronic.parse('1 minute ago')}]
380
+ })
381
+ end
382
+
383
+ specify { expect(subject).to eq([]) }
384
+ end
385
+ end
386
+
387
+ end
388
+
389
+ describe '#last_comment' do
390
+ subject { pr.last_comment }
391
+
392
+ before do
393
+ FakeGitHub.new(
394
+ repo_owner: user,
395
+ repo_name: repo,
396
+ pull_request: {
397
+ number: existing_pull_request.number,
398
+ owner: existing_pull_request.head.user.login,
399
+ comments: [{author: 'tito', body: 'lgtm'}, {author: 'ringo', body: 'Cha cha cha'}]
400
+ })
401
+ end
402
+
403
+ specify { expect(subject).to eq('"Cha cha cha"') }
404
+ end
405
+
406
+ describe '#build' do
407
+ let(:build) { Fixture.new('repositories/statuses.json').to_json_hashie.first }
408
+
409
+ subject { pr.build }
410
+
411
+ context "with an existing build" do
412
+ specify { expect(subject.state).to eq(build.state) }
413
+ specify { expect(subject.description).to eq(build.description) }
414
+ specify { expect(subject.url).to eq(build.target_url) }
415
+ end
416
+
417
+ context "no build found" do
418
+ before { allow(GitReflow.git_server).to receive(:get_build_status).and_return(nil) }
419
+ specify { expect(subject.state).to eq(nil) }
420
+ specify { expect(subject.description).to eq(nil) }
421
+ specify { expect(subject.url).to eq(nil) }
422
+ end
423
+ end
424
+
425
+ describe '#merge!' do
426
+ let(:inputs) do
427
+ {
428
+ :base => "base_branch",
429
+ :title => "title",
430
+ :message => "message"
431
+ }
432
+ end
433
+
434
+ let(:lgtm_comment_authors) {
435
+ ["simonzhu24", "reenhanced"]
436
+ }
437
+
438
+ let(:merge_response) { { :message => "Failure_Message" } }
439
+
440
+ subject { pr.merge! inputs }
441
+
442
+ before do
443
+ allow(GitReflow).to receive(:git_server).and_return(github)
444
+ allow(GitReflow::Config).to receive(:get)
445
+ allow(GitReflow.git_server).to receive(:connection).and_return(github_api)
446
+ allow(GitReflow.git_server).to receive(:get_build_status).and_return(Struct.new(:state, :description, :target_url).new())
447
+ allow_any_instance_of(GitReflow::GitServer::PullRequest).to receive(:commit_message_for_merge).and_return('Bingo')
448
+ allow_any_instance_of(GitReflow).to receive(:append_to_squashed_commit_message).and_return(true)
449
+ end
450
+
451
+ context "and force-merging" do
452
+ let(:inputs) do
453
+ {
454
+ base: "base_branch",
455
+ title: "title",
456
+ message: "message",
457
+ skip_lgtm: true
458
+ }
459
+ end
460
+
461
+ before { allow_any_instance_of(GitReflow::GitServer::PullRequest).to receive(:deliver?).and_return(true) }
462
+
463
+ it "falls back on manual squash merge" do
464
+ expect { subject }.to have_run_command "git merge --squash #{feature_branch_name}"
465
+ end
466
+ end
467
+
468
+ context "and always deliver is set" do
469
+ before do
470
+ allow(GitReflow::Config).to receive(:get).with('reflow.always-deliver').and_return('true')
471
+ allow(github_api).to receive_message_chain(:pull_requests, :merge).and_return(double(success?: true))
472
+ end
473
+
474
+ it "doesn't ask to confirm deliver" do
475
+ expect(pr).to_not receive(:ask).with('This is the current status of your Pull Request. Are you sure you want to deliver? ')
476
+ subject
477
+ end
478
+ end
479
+
480
+ context "and not suqash merging" do
481
+ let(:inputs) do
482
+ {
483
+ base: "base_branch",
484
+ title: "title",
485
+ message: "message",
486
+ merge_method: "merge"
487
+ }
488
+ end
489
+
490
+ before do
491
+ allow_any_instance_of(GitReflow::GitServer::PullRequest).to receive(:deliver?).and_return(true)
492
+ allow(github_api).to receive_message_chain(:pull_requests, :merge).and_return(double(success?: true))
493
+ end
494
+
495
+ it "doesn't ask Github to squash merge" do
496
+ expect(github_api).to receive_message_chain(:pull_requests, :merge).with(
497
+ user,
498
+ repo,
499
+ pr.number.to_s,
500
+ {
501
+ "commit_title" => "#{inputs[:title]}",
502
+ "commit_message" => "#{inputs[:message]}\n",
503
+ "sha" => pr.head.sha,
504
+ "merge_method" => "merge"
505
+ }
506
+ )
507
+
508
+ subject
509
+ end
510
+ end
511
+
512
+ context "finds pull request but merge response fails" do
513
+ before do
514
+ allow(GitReflow::GitServer::GitHub).to receive_message_chain(:connection, :pull_requests, :merge).and_return(merge_response)
515
+ allow(merge_response).to receive(:success?).and_return(false)
516
+ allow_any_instance_of(GitReflow::GitServer::GitHub::PullRequest).to receive(:approvals).and_return(lgtm_comment_authors)
517
+ allow(pr).to receive(:deliver?).and_return(true)
518
+ allow(merge_response).to receive(:to_s).and_return("Merge failed")
519
+ end
520
+
521
+ it "throws an error" do
522
+ expect { subject }.to have_said "Merge failed", :deliver_halted
523
+ expect { subject }.to have_said "There were problems commiting your feature... please check the errors above and try again.", :error
524
+ end
525
+ end
526
+ end
527
+
528
+ describe '.create(options)' do
529
+ let(:title) { 'Bone Saw is ready!' }
530
+ let(:body) { 'Snap into a Slim Jim!' }
531
+ let(:base_branch_name) { 'base-branch' }
532
+ let(:pull_request_response) do
533
+ Fixture.new('pull_requests/pull_request.json.erb',
534
+ number: 2,
535
+ title: title,
536
+ body: body,
537
+ base_branch: base_branch_name,
538
+ repo_owner: user,
539
+ repo_name: repo)
540
+ end
541
+
542
+ subject { GitReflow::GitServer::GitHub::PullRequest.create(title: title, body: body, base: base_branch_name) }
543
+
544
+ before do
545
+ stub_request(:post, %r{/repos/#{user}/#{repo}/pulls}).
546
+ to_return(body: pull_request_response.to_s, status: 201, headers: {content_type: "application/json; charset=utf-8"})
547
+ end
548
+
549
+ specify { expect(subject.class.to_s).to eql('GitReflow::GitServer::GitHub::PullRequest') }
550
+ specify { expect(subject.title).to eql(title) }
551
+ specify { expect(subject.description).to eql(body) }
552
+ specify { expect(subject.base_branch_name).to eql(base_branch_name) }
553
+ end
554
+
555
+ describe '.find_open(options)' do
556
+ let(:feature_branch) { 'new-feature' }
557
+ let(:base_branch) { 'base-branch' }
558
+
559
+ subject { GitReflow::GitServer::GitHub::PullRequest.find_open(from: feature_branch, to: base_branch) }
560
+
561
+ before do
562
+ allow(GitReflow.git_server.class).to receive(:current_branch).and_return(feature_branch)
563
+ FakeGitHub.new(
564
+ repo_owner: user,
565
+ repo_name: repo,
566
+ pull_request: {
567
+ number: existing_pull_request.number,
568
+ owner: existing_pull_request.head.user.login,
569
+ base_branch: base_branch,
570
+ feature_branch: feature_branch
571
+ })
572
+ end
573
+
574
+ specify { expect(subject.class.to_s).to eql('GitReflow::GitServer::GitHub::PullRequest') }
575
+ specify { expect(subject.number).to eql(existing_pull_request.number) }
576
+
577
+ context "without any options" do
578
+ let(:base_branch) { 'master' }
579
+ subject { GitReflow::GitServer::GitHub::PullRequest.find_open() }
580
+ it "defaults to the current branch as the feature branch and 'master' as the base branch" do
581
+ expect(subject.class.to_s).to eql('GitReflow::GitServer::GitHub::PullRequest')
582
+ expect(subject.number).to eql(existing_pull_request.number)
583
+ end
584
+ end
585
+ end
586
+
587
+ end