git_reflow 0.8.10 → 0.9.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/multi-ruby-tests.yml +33 -0
  3. data/.rubocop.yml +2 -0
  4. data/.ruby-version +1 -1
  5. data/Appraisals +1 -6
  6. data/CHANGELOG.md +466 -348
  7. data/Gemfile.lock +100 -70
  8. data/LICENSE +20 -20
  9. data/README.md +36 -12
  10. data/Rakefile +15 -8
  11. data/Workflow +3 -0
  12. data/bin/console +7 -7
  13. data/bin/setup +6 -6
  14. data/exe/git-reflow +14 -30
  15. data/git_reflow.gemspec +25 -24
  16. data/lib/git_reflow.rb +3 -14
  17. data/lib/git_reflow/config.rb +52 -17
  18. data/lib/git_reflow/git_helpers.rb +69 -22
  19. data/lib/git_reflow/git_server/base.rb +68 -68
  20. data/lib/git_reflow/git_server/git_hub.rb +53 -40
  21. data/lib/git_reflow/git_server/git_hub/pull_request.rb +25 -17
  22. data/lib/git_reflow/git_server/pull_request.rb +19 -3
  23. data/lib/git_reflow/merge_error.rb +9 -9
  24. data/lib/git_reflow/rspec.rb +1 -0
  25. data/lib/git_reflow/rspec/command_line_helpers.rb +23 -6
  26. data/lib/git_reflow/rspec/stub_helpers.rb +13 -13
  27. data/lib/git_reflow/rspec/workflow_helpers.rb +18 -0
  28. data/lib/git_reflow/sandbox.rb +16 -6
  29. data/lib/git_reflow/version.rb +1 -1
  30. data/lib/git_reflow/workflow.rb +305 -10
  31. data/lib/git_reflow/workflows/FlatMergeWorkflow +38 -0
  32. data/lib/git_reflow/workflows/core.rb +208 -79
  33. data/spec/fixtures/authentication_failure.json +3 -0
  34. data/spec/fixtures/awesome_workflow.rb +2 -6
  35. data/spec/fixtures/git/git_config +7 -7
  36. data/spec/fixtures/issues/comment.json.erb +27 -27
  37. data/spec/fixtures/issues/comments.json +29 -29
  38. data/spec/fixtures/issues/comments.json.erb +15 -15
  39. data/spec/fixtures/pull_requests/comment.json.erb +45 -45
  40. data/spec/fixtures/pull_requests/comments.json +47 -47
  41. data/spec/fixtures/pull_requests/comments.json.erb +15 -15
  42. data/spec/fixtures/pull_requests/commits.json +29 -29
  43. data/spec/fixtures/pull_requests/external_pull_request.json +145 -145
  44. data/spec/fixtures/pull_requests/pull_request.json +142 -142
  45. data/spec/fixtures/pull_requests/pull_request.json.erb +142 -142
  46. data/spec/fixtures/pull_requests/pull_request_branch_nonexistent_error.json +32 -0
  47. data/spec/fixtures/pull_requests/pull_request_exists_error.json +32 -32
  48. data/spec/fixtures/pull_requests/pull_requests.json +136 -136
  49. data/spec/fixtures/repositories/commit.json +53 -53
  50. data/spec/fixtures/repositories/commit.json.erb +53 -53
  51. data/spec/fixtures/repositories/commits.json.erb +13 -13
  52. data/spec/fixtures/repositories/statuses.json +31 -31
  53. data/spec/fixtures/users/user.json +32 -0
  54. data/spec/lib/git_reflow/git_helpers_spec.rb +115 -12
  55. data/spec/lib/git_reflow/git_server/git_hub/pull_request_spec.rb +6 -6
  56. data/spec/lib/git_reflow/git_server/git_hub_spec.rb +77 -3
  57. data/spec/lib/git_reflow/git_server/pull_request_spec.rb +41 -7
  58. data/spec/lib/git_reflow/workflow_spec.rb +259 -14
  59. data/spec/lib/git_reflow/workflows/core_spec.rb +224 -65
  60. data/spec/lib/git_reflow/workflows/flat_merge_spec.rb +17 -6
  61. data/spec/lib/git_reflow_spec.rb +2 -25
  62. data/spec/spec_helper.rb +3 -0
  63. data/spec/support/github_helpers.rb +1 -1
  64. data/spec/support/mock_pull_request.rb +17 -17
  65. data/spec/support/web_mocks.rb +39 -39
  66. metadata +52 -53
  67. data/circle.yml +0 -26
  68. data/lib/git_reflow/commands/deliver.rb +0 -10
  69. data/lib/git_reflow/commands/refresh.rb +0 -20
  70. data/lib/git_reflow/commands/review.rb +0 -13
  71. data/lib/git_reflow/commands/setup.rb +0 -11
  72. data/lib/git_reflow/commands/stage.rb +0 -9
  73. data/lib/git_reflow/commands/start.rb +0 -18
  74. data/lib/git_reflow/commands/status.rb +0 -7
  75. data/lib/git_reflow/workflows/flat_merge.rb +0 -10
  76. data/spec/fixtures/workflow_with_super.rb +0 -8
@@ -86,21 +86,21 @@ describe GitReflow::GitServer::GitHub::PullRequest do
86
86
  pull_request: {
87
87
  number: existing_pull_request.number,
88
88
  comments: [{author: comment_author}],
89
- reviews: []
89
+ reviews: [{author: existing_pull_request.user.login}]
90
90
  },
91
91
  issue: {
92
92
  number: existing_pull_request.number,
93
- comments: [{author: comment_author}]
93
+ comments: [{author: comment_author}, {author: existing_pull_request.user.login}]
94
94
  }
95
95
  )
96
96
  end
97
- specify { expect(subject).to eql(existing_pull_comments.to_a + existing_issue_comments.to_a) }
97
+ specify { expect(subject).to eql(existing_pull_comments.to_a + existing_issue_comments.to_a - [existing_pull_request.user.login]) }
98
98
  end
99
99
 
100
100
  context "Testing Nil Comments" do
101
101
  before do
102
102
  stub_request(:get, "https://api.github.com/repos/reenhanced/repo/pulls/2/comments?access_token=a1b2c3d4e5f6g7h8i9j0").
103
- 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'}).
103
+ 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.19.0'}).
104
104
  to_return(:status => 200, :body => "", :headers => {})
105
105
 
106
106
  FakeGitHub.new(
@@ -133,7 +133,7 @@ describe GitReflow::GitServer::GitHub::PullRequest do
133
133
  number: existing_pull_request.number,
134
134
  owner: existing_pull_request.user.login,
135
135
  comments: [{author: 'tito'}, {author: 'bobby'}, {author: 'ringo'}],
136
- reviews: [{author: 'nature-boy'}]
136
+ reviews: [{author: 'ringo'}, {author: 'nature-boy'}]
137
137
  },
138
138
  issue: {
139
139
  number: existing_pull_request.number,
@@ -484,7 +484,7 @@ describe GitReflow::GitServer::GitHub::PullRequest do
484
484
  allow(GitReflow.git_server).to receive(:connection).and_return(github_api)
485
485
  allow(GitReflow.git_server).to receive(:get_build_status).and_return(Struct.new(:state, :description, :target_url).new())
486
486
  allow_any_instance_of(GitReflow::GitServer::PullRequest).to receive(:commit_message_for_merge).and_return('Bingo')
487
- allow_any_instance_of(GitReflow).to receive(:append_to_squashed_commit_message).and_return(true)
487
+ allow_any_instance_of(GitReflow).to receive(:append_to_merge_commit_message).and_return(true)
488
488
  end
489
489
 
490
490
  context "and force-merging" do
@@ -78,7 +78,7 @@ describe GitReflow::GitServer::GitHub do
78
78
  subject { github.authenticate }
79
79
 
80
80
  before do
81
- allow(GitReflow::GitServer::GitHub).to receive(:user).and_return('reenhanced')
81
+ allow(GitReflow::GitServer::GitHub).to receive(:user).and_return(user)
82
82
  allow(github_api).to receive(:oauth).and_return(github_authorizations)
83
83
  allow(github_api).to receive_message_chain(:oauth, :all).and_return([])
84
84
  allow(github).to receive(:run).with('hostname', loud: false).and_return(hostname)
@@ -151,12 +151,86 @@ describe GitReflow::GitServer::GitHub do
151
151
  body: { error: "GET https://api.github.com/authorizations: 401 Bad credentials" }
152
152
  }}
153
153
 
154
+ before do
155
+ allow(GitReflow::Config).to receive(:get).and_call_original
156
+ allow(GitReflow::Config).to receive(:get).with('github.oauth-token').and_return(oauth_token_hash[:token])
157
+ allow(Github::Client).to receive(:new).and_return(github_api)
158
+ allow(github_authorizations).to receive(:authenticated?).and_return(true)
159
+ allow(github_api.oauth).to receive(:create).with({ scopes: ['repo'], note: "git-reflow (#{hostname})" }).and_return(oauth_token_hash)
160
+
161
+ stub_request(:get, %r{/user}).
162
+ to_return(
163
+ body: Fixture.new('authentication_failure.json').to_s,
164
+ status: 401,
165
+ headers: {'content-type' => 'application/json; charset=utf-8', status: 'Unauthorized'},
166
+ )
167
+ end
168
+
169
+ it "notifies the user of successful setup" do
170
+ expect { subject }.to have_said "Your GitHub account was successfully setup!", :success
171
+ end
172
+
173
+ it "creates a new GitHub oauth token" do
174
+ expect(github_api.oauth).to receive(:create).and_return(oauth_token_hash)
175
+ subject
176
+ end
177
+
178
+ it "creates git config keys for github connections" do
179
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all github.site \"#{github_site}\"", blocking: false
180
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all github.endpoint \"#{github_api_endpoint}\"", blocking: false
181
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all github.oauth-token \"#{oauth_token_hash[:token]}\"", blocking: false
182
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all reflow.git-server \"GitHub\"", blocking: false
183
+ end
184
+
185
+ end
186
+ end
187
+
188
+ context 'already authenticated' do
189
+ let(:oauth_token) { "abc123" }
190
+
191
+ before do
192
+ allow(GitReflow::Config).to receive(:get).and_call_original
193
+ allow(GitReflow::Config).to receive(:get).with('github.oauth-token').and_return(oauth_token)
194
+ end
195
+
196
+ context "and authentication token is still valid" do
197
+ before do
198
+ stub_request(:get, %r{/user}).
199
+ to_return(
200
+ body: Fixture.new('users/user.json').to_s,
201
+ status: 200,
202
+ headers: { content_type: "application/json; charset=utf-8" }
203
+ )
204
+
205
+ allow(Github::Client).to receive(:new).and_return(github_api)
206
+ allow(github_api).to receive(:oauth).and_return(github_authorizations)
207
+ allow(github_authorizations).to receive(:authenticated?).and_return(true)
208
+ allow(github_api.oauth).to receive(:create).with({ scopes: ['repo'], note: "git-reflow (#{hostname})" }).and_return(oauth_token_hash)
209
+ end
210
+
211
+ it "resolves all missing git-reflow configurations" do
212
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all github.site \"#{github_site}\"", blocking: false
213
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all github.endpoint \"#{github_api_endpoint}\"", blocking: false
214
+ expect{ subject }.to have_run_command_silently "git config -f #{GitReflow::Config::CONFIG_FILE_PATH} --replace-all reflow.git-server \"GitHub\"", blocking: false
215
+ expect { subject }.to have_said "Your GitHub account was already setup with: "
216
+ expect { subject }.to have_said "\tUser Name: #{user}"
217
+ expect { subject }.to have_said "\tEndpoint: #{github_api_endpoint}"
218
+ end
219
+ end
220
+
221
+ context "and authentication token is expired" do
222
+ let(:unauthorized_error_response) {{
223
+ response_headers: {'content-type' => 'application/json; charset=utf-8', status: 'Unauthorized'},
224
+ method: 'GET',
225
+ status: '401',
226
+ body: { error: "GET https://api.github.com/authorizations: 401 Bad credentials" }
227
+ }}
228
+
154
229
  before do
155
230
  allow(Github::Client).to receive(:new).and_raise Github::Error::Unauthorized.new(unauthorized_error_response)
156
231
  end
157
232
 
158
- it "notifies user of invalid login details" do
159
- expect { subject }.to have_said "Github Authentication Error: #{Github::Error::Unauthorized.new(unauthorized_error_response).inspect}", :error
233
+ it "requests a new oauth token" do
160
234
  end
161
235
  end
162
236
  end
@@ -364,7 +364,7 @@ describe GitReflow::GitServer::PullRequest do
364
364
  subject { pr.merge! inputs }
365
365
 
366
366
  before do
367
- allow(GitReflow).to receive(:append_to_squashed_commit_message)
367
+ allow(GitReflow).to receive(:append_to_merge_commit_message)
368
368
  allow(pr).to receive(:commit_message_for_merge).and_return(commit_message_for_merge)
369
369
  end
370
370
 
@@ -376,7 +376,7 @@ describe GitReflow::GitServer::PullRequest do
376
376
  it "updates both feature and destination branch and squash-merges feature into base branch" do
377
377
  expect(GitReflow).to receive(:update_current_branch)
378
378
  expect(GitReflow).to receive(:fetch_destination).with(pr.base_branch_name)
379
- expect(GitReflow).to receive(:append_to_squashed_commit_message).with(pr.commit_message_for_merge)
379
+ expect(GitReflow).to receive(:append_to_merge_commit_message).with(pr.commit_message_for_merge)
380
380
  expect { subject }.to have_run_commands_in_order [
381
381
  "git checkout #{pr.base_branch_name}",
382
382
  "git pull origin #{pr.base_branch_name}",
@@ -470,6 +470,12 @@ describe GitReflow::GitServer::PullRequest do
470
470
  before { allow(pr).to receive(:approvals).and_return(['sally', 'joey']) }
471
471
  specify { expect(subject).to include "\nLGTM given by: @sally, @joey\n" }
472
472
  end
473
+
474
+ context "with custom merge commit message template" do
475
+ before { allow(GitReflow).to receive(:merge_commit_template).and_return("Super cool changes") }
476
+ specify { expect(subject).to include "Super cool changes" }
477
+ specify { expect(subject).to_not include "\nMerges ##{pr.number}\n" }
478
+ end
473
479
  end
474
480
 
475
481
  context "#cleanup_feature_branch?" do
@@ -485,14 +491,42 @@ describe GitReflow::GitServer::PullRequest do
485
491
  allow(GitReflow::Config).to receive(:get).with('reflow.always-cleanup').and_return('false')
486
492
  end
487
493
 
488
- context "and user chooses to cleanup" do
489
- before { expect(pr).to receive(:ask).with('Would you like to push this branch to your remote repo and cleanup your feature branch? ').and_return('yes') }
494
+ context "and always cleanup local config is set" do
495
+ end
496
+
497
+ context "and always cleanup remote config is set" do
498
+ end
499
+
500
+ context "and user chooses to cleanup local only" do
501
+ before do
502
+ expect(pr).to receive(:ask).with('Would you like to cleanup your local feature branch? ').and_return('yes')
503
+ allow(pr).to receive(:ask).with('Would you like to cleanup your remote feature branch? ').and_return('no')
504
+ end
505
+ it { should be_truthy }
506
+ end
507
+
508
+ context "and user chooses to cleanup remote only" do
509
+ before do
510
+ expect(pr).to receive(:ask).with('Would you like to cleanup your local feature branch? ').and_return('no')
511
+ expect(pr).to receive(:ask).with('Would you like to cleanup your remote feature branch? ').and_return('yes')
512
+ end
490
513
  it { should be_truthy }
491
514
  end
492
515
 
493
- context "and user choose not to cleanup" do
494
- before { expect(pr).to receive(:ask).with('Would you like to push this branch to your remote repo and cleanup your feature branch? ').and_return('no') }
495
- it { should be_falsy }
516
+ context "and user chooses to cleanup local and remote" do
517
+ before do
518
+ allow(pr).to receive(:ask).with('Would you like to cleanup your local feature branch? ').and_return('yes')
519
+ allow(pr).to receive(:ask).with('Would you like to cleanup your remote feature branch? ').and_return('yes')
520
+ end
521
+ it { should be_truthy }
522
+ end
523
+
524
+ context "and user chooses to cleanup neither local nor remote" do
525
+ before do
526
+ expect(pr).to receive(:ask).with('Would you like to cleanup your local feature branch? ').and_return('no')
527
+ allow(pr).to receive(:ask).with('Would you like to cleanup your remote feature branch? ').and_return('no')
528
+ end
529
+ it { should be_falsey }
496
530
  end
497
531
  end
498
532
  end
@@ -6,54 +6,299 @@ describe GitReflow::Workflow do
6
6
  include GitReflow::Workflow
7
7
  end
8
8
 
9
+ class DummyBundler
10
+ def gemfile(&block)
11
+ instance_eval &block
12
+ end
13
+
14
+ def source(name); end
15
+ def gem(name, *args); end
16
+ end
17
+
18
+ class DummyGemifiedWorkflow
19
+ include GitReflow::Workflow
20
+
21
+ command :whirl do
22
+ puts "whirl"
23
+ end
24
+ end
25
+
9
26
  let(:workflow) { DummyWorkflow }
10
27
  let(:loader) { double() }
11
28
 
12
29
  describe ".current" do
13
30
  subject { GitReflow::Workflow.current }
14
31
 
32
+ before do
33
+ allow(GitReflow::Workflows::Core).to receive(:load_raw_workflow)
34
+ end
35
+
15
36
  context "when no workflow is set" do
16
37
  before { allow(GitReflow::Config).to receive(:get).with("reflow.workflow").and_return('') }
17
38
  specify { expect( subject ).to eql(GitReflow::Workflows::Core) }
18
39
  end
19
40
 
20
- context "when a workflow is set" do
41
+ context "when a global workflow is set" do
21
42
  let(:workflow_path) { File.join(File.expand_path("../../../fixtures", __FILE__), "/awesome_workflow.rb") }
22
43
 
23
44
  before { allow(GitReflow::Config).to receive(:get).with("reflow.workflow").and_return(workflow_path) }
24
- specify { expect( subject ).to eql(GitReflow::Workflow::AwesomeWorkflow) }
45
+ specify { expect( subject ).to eql(GitReflow::Workflows::Core) }
46
+ end
47
+
48
+ context "when a local workflow is set" do
49
+ let(:workflow_content) do
50
+ <<~WORKFLOW_CONTENT
51
+ command :dummy do
52
+ GitReflow.say "derp"
53
+ end
54
+ WORKFLOW_CONTENT
55
+ end
56
+
57
+ before do
58
+ allow(File).to receive(:exists?).with("#{GitReflow.git_root_dir}/Workflow").and_return(true)
59
+ allow(File).to receive(:read).with("#{GitReflow.git_root_dir}/Workflow").and_return(workflow_content)
60
+ expect(GitReflow::Workflows::Core).to receive(:load_raw_workflow).with(workflow_content).and_call_original
61
+ end
62
+
63
+ specify { expect( subject ).to respond_to(:dummy) }
64
+ specify { expect( subject ).to eql(GitReflow::Workflows::Core) }
65
+ end
66
+
67
+ context "when both a local and a global workflow are set" do
68
+ let(:workflow_path) { File.join(File.expand_path("../../../fixtures", __FILE__), "/awesome_workflow.rb") }
69
+ let(:workflow_content) do
70
+ <<~WORKFLOW_CONTENT
71
+ command :dummy do
72
+ GitReflow.say "derp"
73
+ end
74
+ WORKFLOW_CONTENT
75
+ end
76
+
77
+ before do
78
+ allow(File).to receive(:exists?).with("#{GitReflow.git_root_dir}/Workflow").and_return(true)
79
+ allow(File).to receive(:read).with("#{GitReflow.git_root_dir}/Workflow").and_return(workflow_content)
80
+ allow(GitReflow::Config).to receive(:get).with("reflow.workflow").and_return(workflow_path)
81
+ allow(GitReflow::Workflows::Core).to receive(:load_raw_workflow).and_call_original
82
+ end
83
+
84
+ specify { expect(subject).to respond_to(:dummy) }
85
+ specify { expect(subject).to eql(GitReflow::Workflows::Core) }
86
+ end
87
+ end
88
+
89
+ describe ".before" do
90
+ it "executes the block before the command" do
91
+ GitReflow::Workflows::Core.load_raw_workflow <<~WORKFLOW_CONTENT
92
+ command :yips do
93
+ puts "Yips."
94
+ end
95
+
96
+ before :yips do
97
+ puts "Would you like a donut?"
98
+ end
99
+ WORKFLOW_CONTENT
100
+
101
+ allow(GitReflow::Workflows::Core).to receive(:load_workflow).and_return(true)
102
+
103
+ expect { GitReflow.workflow.yips }.to have_output "Would you like a donut?\nYips."
104
+ end
105
+
106
+ it "executes blocks sequentially by order of appearance" do
107
+ GitReflow::Workflows::Core.load_raw_workflow <<~WORKFLOW_CONTENT
108
+ command :yips do
109
+ puts "Yips."
110
+ end
111
+
112
+ before :yips do
113
+ puts "Cupcake?"
114
+ end
115
+
116
+ before :yips do
117
+ puts "Would you like a donut?"
118
+ end
119
+ WORKFLOW_CONTENT
120
+
121
+ allow(GitReflow::Workflows::Core).to receive(:load_workflow).and_return(true)
122
+
123
+ expect { GitReflow.workflow.yips }.to have_output "Cupcake?\nWould you like a donut?\nYips."
124
+ end
125
+
126
+ it "proxies any arguments returned to the command" do
127
+ GitReflow::Workflows::Core.load_raw_workflow <<~WORKFLOW_CONTENT
128
+ command :yips, arguments: { spiced: false } do |**params|
129
+ puts params[:spiced] ? "Too spicy." : "Yips."
130
+ end
131
+
132
+ before :yips do
133
+ puts "Wasabe?"
134
+ { spiced: true }
135
+ end
136
+ WORKFLOW_CONTENT
137
+
138
+ allow(GitReflow::Workflows::Core).to receive(:load_workflow).and_return(true)
139
+
140
+ expect { GitReflow.workflow.yips }.to have_output "Wasabe?\nToo spicy."
141
+ end
142
+ end
143
+
144
+ describe ".after" do
145
+ it "executes the block after the command" do
146
+ GitReflow::Workflows::Core.load_raw_workflow <<~WORKFLOW_CONTENT
147
+ command :vroom do
148
+ puts "Vroom"
149
+ end
150
+
151
+ after :vroom do
152
+ puts "VROOOOM"
153
+ end
154
+ WORKFLOW_CONTENT
155
+
156
+ allow(GitReflow::Workflows::Core).to receive(:load_workflow).and_return(true)
157
+
158
+ expect { GitReflow.workflow.vroom }.to have_output "Vroom\nVROOOOM"
159
+ end
160
+
161
+ it "executes blocks sequentially by order of appearance" do
162
+ GitReflow::Workflows::Core.load_raw_workflow <<~WORKFLOW_CONTENT
163
+ command :vroom do
164
+ puts "Vroom"
165
+ end
166
+
167
+ after :vroom do
168
+ puts "Vrooom"
169
+ end
170
+
171
+ after :vroom do
172
+ puts "VROOOOM"
173
+ end
174
+ WORKFLOW_CONTENT
175
+
176
+ allow(GitReflow::Workflows::Core).to receive(:load_workflow).and_return(true)
177
+
178
+ expect { GitReflow.workflow.vroom }.to have_output "Vroom\nVrooom\nVROOOOM"
25
179
  end
26
180
  end
27
181
 
28
182
  describe ".command" do
29
183
  it "creates a class method for a bogus command" do
30
- class DummyWorkflow
31
- include GitReflow::Workflow
32
- end
33
184
  workflow.command :bogus do
34
- "Woohoo"
185
+ GitReflow.say "Woohoo"
35
186
  end
36
187
 
37
- expect(DummyWorkflow.bogus).to eql("Woohoo")
188
+ expect { DummyWorkflow.bogus }.to have_said("Woohoo")
38
189
  end
39
190
 
40
191
  it "creates a method for a bogus command with arguments" do
41
- workflow.command :bogus, arguments: [:feature_branch] do |**params|
42
- "Woohoo #{params[:feature_branch]}!"
192
+ workflow.command :bogus, arguments: { feature_branch: nil } do |**params|
193
+ GitReflow.say "Woohoo #{params[:feature_branch]}!"
43
194
  end
44
195
 
45
- expect(DummyWorkflow.bogus(feature_branch: "donuts")).to eql("Woohoo donuts!")
196
+ expect { DummyWorkflow.bogus(feature_branch: "arguments") }.to have_said("Woohoo arguments!")
46
197
  end
47
198
 
48
- it "creates a class method for a bogus command with default options" do
49
- workflow.command :bogus, arguments: [:feature_branch], defaults: {decoration: 'sprinkles'} do |**params|
199
+ it "creates a class method for a bogus command with default arguments" do
200
+ workflow.command :bogus, arguments: { feature_branch: nil, decoration: "sprinkles" } do |**params|
50
201
  donut_excitement = "Woohoo #{params[:feature_branch]}"
51
202
  donut_excitement += " with #{params[:decoration]}" if params[:decoration]
52
- "#{donut_excitement}!"
203
+ GitReflow.say "#{donut_excitement}!"
204
+ end
205
+
206
+ expect { DummyWorkflow.bogus(feature_branch: "donuts") }.to have_said("Woohoo donuts with sprinkles!")
207
+ end
208
+
209
+ it "creates a class method for a bogus command with flags" do
210
+ workflow.command :bogus, flags: { feature_branch: nil } do |**params|
211
+ GitReflow.say "Woohoo #{params[:feature_branch]}!"
212
+ end
213
+
214
+ expect { DummyWorkflow.bogus(feature_branch: "flags") }.to have_said("Woohoo flags!")
215
+ end
216
+
217
+ it "creates a class method for a bogus command with default flags" do
218
+ workflow.command :bogus, flags: { feature_branch: "donuts" } do |**params|
219
+ GitReflow.say "Woohoo #{params[:feature_branch]}!"
220
+ end
221
+
222
+ expect { DummyWorkflow.bogus }.to have_said("Woohoo donuts!")
223
+ end
224
+
225
+ it "creates a class method for a bogus command with switches" do
226
+ workflow.command :bogus, switches: { feature_branch: nil } do |**params|
227
+ GitReflow.say "Woohoo #{params[:feature_branch]}!"
228
+ end
229
+
230
+ expect { DummyWorkflow.bogus(feature_branch: "switches") }.to have_said("Woohoo switches!")
231
+ end
232
+
233
+ it "creates a class method for a bogus command with default switches" do
234
+ workflow.command :bogus, switches: { feature_branch: "donuts" } do |**params|
235
+ GitReflow.say "Woohoo #{params[:feature_branch]}!"
53
236
  end
54
237
 
55
- expect(DummyWorkflow.bogus(feature_branch: "donuts")).to eql("Woohoo donuts with sprinkles!")
238
+ expect { DummyWorkflow.bogus }.to have_said("Woohoo donuts!")
56
239
  end
57
240
  end
58
241
 
242
+ describe ".use(workflow_name)" do
243
+ it "Uses a pre-existing workflow as a basis" do
244
+ allow(GitReflow::Workflows::Core).to receive(:load_workflow)
245
+ expect(GitReflow::Workflows::Core).to receive(:load_workflow)
246
+ .with(workflow.workflows["FlatMergeWorkflow"])
247
+ .and_return(true)
248
+ workflow.use "FlatMergeWorkflow"
249
+ end
250
+ end
251
+
252
+ describe ".use_gem(name, *ags)" do
253
+ let(:mock_bundler) { DummyBundler.new }
254
+
255
+ before do
256
+ allow(DummyGemifiedWorkflow).to receive(:gemfile) do |&block|
257
+ mock_bundler.gemfile(&block)
258
+ end
259
+ stub_run_for(DummyGemifiedWorkflow)
260
+ end
261
+
262
+ it "Installs a gem using Bundler's inline gemfile" do
263
+ stub_command(command: "gem list -ie whirly", options: { loud: false, raise: true }, return_value: "false")
264
+ expect(mock_bundler).to receive(:source).with("https://rubygems.org")
265
+ expect(mock_bundler).to receive(:gem).with("whirly", "0.2.6")
266
+
267
+ DummyGemifiedWorkflow.class_eval do
268
+ use_gem "whirly", "0.2.6"
269
+ end
270
+ end
271
+
272
+ it "Uses an existing gem if it's already installed" do
273
+ stub_command(command: "gem list -ie whirly", options: { loud: false, raise: false }, return_value: "true")
274
+ expect(DummyGemifiedWorkflow).to_not receive(:gemfile)
275
+
276
+ DummyGemifiedWorkflow.class_eval do
277
+ use_gem "whirly", "0.2.6"
278
+ end
279
+ end
280
+ end
281
+
282
+ describe ".use_gemfile(&block)" do
283
+ let(:mock_bundler) { DummyBundler.new }
284
+
285
+ before do
286
+ allow(DummyGemifiedWorkflow).to receive(:gemfile) do |&block|
287
+ mock_bundler.gemfile(&block)
288
+ end
289
+ stub_run_for(DummyGemifiedWorkflow)
290
+ end
291
+
292
+ it "runs bundler's inline gemfile with the provided block" do
293
+ expect(mock_bundler).to receive(:source).with("https://rubygems.org")
294
+ expect(mock_bundler).to receive(:gem).with("standard")
295
+
296
+ DummyGemifiedWorkflow.class_eval do
297
+ use_gemfile do
298
+ source "https://rubygems.org"
299
+ gem "standard"
300
+ end
301
+ end
302
+ end
303
+ end
59
304
  end