zenflow 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +6 -0
  3. data/.rspec +2 -0
  4. data/.ruby-gemset +1 -0
  5. data/.ruby-version +1 -0
  6. data/.zenflow +10 -0
  7. data/CHANGELOG.md +0 -0
  8. data/Gemfile +3 -0
  9. data/Gemfile.lock +95 -0
  10. data/Guardfile +6 -0
  11. data/LICENSE.md +22 -0
  12. data/README.markdown +92 -0
  13. data/VERSION.yml +5 -0
  14. data/bin/zenflow +17 -0
  15. data/lib/zenflow.rb +35 -0
  16. data/lib/zenflow/cli.rb +130 -0
  17. data/lib/zenflow/commands/deploy.rb +33 -0
  18. data/lib/zenflow/commands/feature.rb +10 -0
  19. data/lib/zenflow/commands/hotfix.rb +15 -0
  20. data/lib/zenflow/commands/release.rb +16 -0
  21. data/lib/zenflow/commands/reviews.rb +12 -0
  22. data/lib/zenflow/helpers/ask.rb +66 -0
  23. data/lib/zenflow/helpers/branch.rb +80 -0
  24. data/lib/zenflow/helpers/branch_command.rb +95 -0
  25. data/lib/zenflow/helpers/branch_commands/abort.rb +21 -0
  26. data/lib/zenflow/helpers/branch_commands/branches.rb +21 -0
  27. data/lib/zenflow/helpers/branch_commands/compare.rb +20 -0
  28. data/lib/zenflow/helpers/branch_commands/deploy.rb +29 -0
  29. data/lib/zenflow/helpers/branch_commands/diff.rb +19 -0
  30. data/lib/zenflow/helpers/branch_commands/finish.rb +68 -0
  31. data/lib/zenflow/helpers/branch_commands/review.rb +58 -0
  32. data/lib/zenflow/helpers/branch_commands/start.rb +39 -0
  33. data/lib/zenflow/helpers/branch_commands/update.rb +22 -0
  34. data/lib/zenflow/helpers/changelog.rb +100 -0
  35. data/lib/zenflow/helpers/config.rb +36 -0
  36. data/lib/zenflow/helpers/github.rb +40 -0
  37. data/lib/zenflow/helpers/help.rb +37 -0
  38. data/lib/zenflow/helpers/log.rb +21 -0
  39. data/lib/zenflow/helpers/pull_request.rb +68 -0
  40. data/lib/zenflow/helpers/repo.rb +13 -0
  41. data/lib/zenflow/helpers/shell.rb +89 -0
  42. data/lib/zenflow/helpers/version.rb +87 -0
  43. data/lib/zenflow/version.rb +3 -0
  44. data/spec/fixtures/VERSION.yml +5 -0
  45. data/spec/fixtures/cassettes/create_bad_pull_request.yml +57 -0
  46. data/spec/fixtures/cassettes/create_pull_request.yml +68 -0
  47. data/spec/fixtures/cassettes/existing_pull_request.yml +145 -0
  48. data/spec/fixtures/cassettes/pull_request_by_ref.yml +145 -0
  49. data/spec/fixtures/cassettes/pull_request_find.yml +70 -0
  50. data/spec/fixtures/cassettes/pull_request_for_non-existent_ref.yml +145 -0
  51. data/spec/fixtures/cassettes/pull_request_list.yml +74 -0
  52. data/spec/fixtures/cassettes/unexisting_pull_request.yml +145 -0
  53. data/spec/spec_helper.rb +36 -0
  54. data/spec/support/shared_examples_for_version_number.rb +19 -0
  55. data/spec/zenflow/commands/deploy_spec.rb +48 -0
  56. data/spec/zenflow/commands/feature_spec.rb +11 -0
  57. data/spec/zenflow/commands/hotfix_spec.rb +14 -0
  58. data/spec/zenflow/commands/release_spec.rb +15 -0
  59. data/spec/zenflow/commands/reviews_spec.rb +15 -0
  60. data/spec/zenflow/helpers/ask_spec.rb +115 -0
  61. data/spec/zenflow/helpers/branch_command_spec.rb +310 -0
  62. data/spec/zenflow/helpers/branch_spec.rb +300 -0
  63. data/spec/zenflow/helpers/changelog_spec.rb +188 -0
  64. data/spec/zenflow/helpers/cli_spec.rb +277 -0
  65. data/spec/zenflow/helpers/github_spec.rb +45 -0
  66. data/spec/zenflow/helpers/help_spec.rb +36 -0
  67. data/spec/zenflow/helpers/log_spec.rb +31 -0
  68. data/spec/zenflow/helpers/pull_request_spec.rb +108 -0
  69. data/spec/zenflow/helpers/shell_spec.rb +135 -0
  70. data/spec/zenflow/helpers/version_spec.rb +111 -0
  71. data/zenflow.gemspec +33 -0
  72. metadata +273 -0
@@ -0,0 +1,36 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ add_filter '/spec/'
4
+ end
5
+
6
+ Dir["./spec/support/**/*.rb"].sort.each {|f| require f}
7
+ require 'zenflow'
8
+ require 'vcr'
9
+
10
+ VCR.configure do |c|
11
+ c.configure_rspec_metadata!
12
+ c.cassette_library_dir = 'spec/fixtures/cassettes'
13
+ c.hook_into :webmock
14
+ c.default_cassette_options = { :record => :new_episodes }
15
+ c.filter_sensitive_data('<GITHUB-USER>'){ Zenflow::Github.user }
16
+ c.filter_sensitive_data('<ZENFLOW-TOKEN>'){ Zenflow::Github.zenflow_token }
17
+ end
18
+
19
+ RSpec.configure do |config|
20
+ config.order = "random"
21
+ config.treat_symbols_as_metadata_keys_with_true_values = true
22
+ config.run_all_when_everything_filtered = true
23
+ config.filter_run :focus => true
24
+
25
+ def capture(stream)
26
+ begin
27
+ stream = stream.to_s
28
+ eval "$#{stream} = StringIO.new"
29
+ yield
30
+ result = eval("$#{stream}").string
31
+ ensure
32
+ eval("$#{stream} = #{stream.upcase}")
33
+ end
34
+ result
35
+ end
36
+ end
@@ -0,0 +1,19 @@
1
+ shared_examples_for "a version" do |version_array|
2
+ it{expect(subject.instance_variable_get('@version')).to(have_key('major'))}
3
+ it{expect(subject.instance_variable_get('@version')).to(have_key('minor'))}
4
+ it{expect(subject.instance_variable_get('@version')).to(have_key('patch'))}
5
+ it{expect(subject.instance_variable_get('@version')).to(have_key('pre'))}
6
+
7
+ it{
8
+ expect(
9
+ subject.instance_variable_get('@version')
10
+ ).to(eq(
11
+ {
12
+ 'major' => version_array[0],
13
+ 'minor' => version_array[1],
14
+ 'patch' => version_array[2],
15
+ 'pre' => version_array[3]
16
+ }
17
+ ) )
18
+ }
19
+ end
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ describe Zenflow::Deploy do
4
+
5
+ describe "Zenflow.Deploy" do
6
+ context 'with migrations' do
7
+ it 'deploys with migrations' do
8
+ Zenflow::Branch.should_receive(:push).with('some-server')
9
+ Zenflow.should_receive(:Log).with("Deploying with migrations to some-server")
10
+ Zenflow::Shell.should_receive(:run).with("cap some-server deploy:migrations")
11
+ Zenflow::Deploy('some-server', :migrations => true)
12
+ end
13
+ end
14
+
15
+ context 'without migrations' do
16
+ it 'deploys without migrations' do
17
+ Zenflow::Branch.should_receive(:push).with('some-server')
18
+ Zenflow.should_receive(:Log).with("Deploying to some-server")
19
+ Zenflow::Shell.should_receive(:run).with("cap some-server deploy")
20
+ Zenflow::Deploy('some-server')
21
+ end
22
+ end
23
+ end
24
+
25
+ subject {Zenflow::Deploy.new}
26
+
27
+ describe '#qa' do
28
+ it 'Deploys to QA' do
29
+ Zenflow.should_receive(:Deploy).with('qa', {})
30
+ subject.qa
31
+ end
32
+ end
33
+
34
+ describe '#staging' do
35
+ it 'Deploys to staging' do
36
+ Zenflow.should_receive(:Deploy).with('staging', {})
37
+ subject.staging
38
+ end
39
+ end
40
+
41
+ describe '#staging' do
42
+ it 'Deploys to production' do
43
+ Zenflow.should_receive(:Deploy).with('production', {})
44
+ subject.production
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe Zenflow::Feature do
4
+
5
+ subject { Zenflow::Feature.new }
6
+
7
+ it { expect(subject.flow).to eq("feature") }
8
+ it { expect(subject.branch(:source)).to eq("master") }
9
+ it { expect(subject.branch(:deploy)).to eq("qa") }
10
+
11
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Zenflow::Hotfix do
4
+
5
+ subject { Zenflow::Hotfix.new }
6
+
7
+ it { expect(subject.flow).to eq("hotfix") }
8
+ it { expect(subject.branch(:source)).to eq("production") }
9
+ it { expect(subject.branch(:deploy)).to match_array(["staging", "qa"]) }
10
+ it { expect(subject.changelog).to eq(:rotate) }
11
+ it { expect(subject.version).to eq(:patch) }
12
+ it { expect(subject.tag).to be_true }
13
+
14
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Zenflow::Release do
4
+
5
+ subject { Zenflow::Release.new }
6
+
7
+ it { expect(subject.flow).to eq("release") }
8
+ it { expect(subject.branch(:source)).to eq("master") }
9
+ it { expect(subject.branch(:destination)).to eq("production") }
10
+ it { expect(subject.branch(:deploy)).to match_array(["staging", "qa"]) }
11
+ it { expect(subject.changelog).to eq(:rotate) }
12
+ it { expect(subject.version).to eq(:minor) }
13
+ it { expect(subject.tag).to be_true }
14
+
15
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Zenflow::Reviews do
4
+
5
+ describe "#list" do
6
+ before do
7
+ pull = double
8
+ pull.stub(:[]).with("number").and_return(1)
9
+ pull.stub(:[]).with("head").and_return({ "ref" => "URL" })
10
+ Zenflow::PullRequest.should_receive(:list).and_return([pull])
11
+ end
12
+ it { capture(:stdout) { Zenflow::Reviews.new.invoke(:list) } }
13
+ end
14
+
15
+ end
@@ -0,0 +1,115 @@
1
+ require 'spec_helper'
2
+
3
+ describe Zenflow do
4
+
5
+ describe "prompt" do
6
+ before do
7
+ Zenflow.stub(:LogToFile)
8
+ $stdin.stub(:gets).and_return("good")
9
+ end
10
+
11
+ it "displays a prompt" do
12
+ Zenflow::Query.should_receive(:print).with(">> How are you? ")
13
+ Zenflow::Ask("How are you?")
14
+ end
15
+
16
+ it "displays a prompt with options" do
17
+ Zenflow::Query.should_receive(:print).with(">> How are you? [good/bad] ")
18
+ Zenflow::Ask("How are you?", options: ["good", "bad"])
19
+ end
20
+
21
+ it "displays a prompt with default" do
22
+ Zenflow::Query.should_receive(:print).with(">> How are you? [good] ")
23
+ Zenflow::Ask("How are you?", default: "good")
24
+ end
25
+
26
+ it "displays a prompt with options and default" do
27
+ Zenflow::Query.should_receive(:print).with(">> How are you? [good/bad] ")
28
+ Zenflow::Ask("How are you?", options: ["good", "bad"], default: "good")
29
+ end
30
+
31
+ context "on error" do
32
+ before(:each) do
33
+ Zenflow::Query.should_receive(:ask_question).at_least(:once).and_return('foo')
34
+ Zenflow::Query.should_receive(:handle_response).once.and_raise('something failed')
35
+ $stdout.should_receive(:puts).once
36
+ end
37
+
38
+ it{expect{Zenflow::Ask('howdy', response: 'foo', error_message: 'something failed')}.to raise_error(/something failed/)}
39
+ end
40
+
41
+ context "on interrupt" do
42
+ before(:each) do
43
+ Zenflow::Query.should_receive(:ask_question).once.and_return('foo')
44
+ Zenflow::Query.should_receive(:handle_response).once.and_raise(Interrupt)
45
+ Zenflow.should_receive(:LogToFile)
46
+ $stdout.should_receive(:puts).at_least(:once)
47
+ end
48
+
49
+ it{expect{Zenflow::Ask('howdy')}.to raise_error(SystemExit)}
50
+ end
51
+ end
52
+
53
+ describe Zenflow::Query do
54
+ describe '.get_response' do
55
+ context 'with a response' do
56
+ it{expect(
57
+ Zenflow::Query.ask_question('foo?', response: 'bar')).to eq('bar')
58
+ }
59
+ end
60
+
61
+ context 'with a response' do
62
+ before(:each) do
63
+ Zenflow::Query.should_receive(:prompt_for_answer).with('foo?',{}).and_return('bar')
64
+ end
65
+
66
+ it{expect(Zenflow::Query.ask_question('foo?')).to eq('bar')}
67
+ end
68
+ end
69
+
70
+ describe '.prompt_for_answer' do
71
+ before(:each) do
72
+ Zenflow::Query.should_receive(:print).with(">> Hi? [yes/bye] ")
73
+ STDIN.should_receive(:gets).and_return("bye")
74
+ end
75
+
76
+ it{expect(
77
+ Zenflow::Query.prompt_for_answer('Hi?', options: ['yes','bye'])
78
+ ).to(
79
+ eq('bye')
80
+ ) }
81
+ end
82
+
83
+ describe '.handle_response' do
84
+ context 'invalid response' do
85
+ before(:each){Zenflow::Query.should_receive(:valid_response?).and_return(false)}
86
+ it{expect{Zenflow::Query.handle_response('foo')}.to raise_error}
87
+ end
88
+
89
+ context 'valid response' do
90
+ before(:each){Zenflow::Query.should_receive(:valid_response?).and_return(true)}
91
+ it{expect(Zenflow::Query.handle_response('foo')).to eq('foo')}
92
+ it{expect(Zenflow::Query.handle_response('Y')).to eq('y')}
93
+ it{expect(Zenflow::Query.handle_response('N')).to eq('n')}
94
+ it{expect(Zenflow::Query.handle_response('', default: 'foo')).to eq('foo')}
95
+ end
96
+ end
97
+
98
+ describe '.valid_response?' do
99
+ it{expect(Zenflow::Query.valid_response?('foo', options: ['foo'])).to eq(true)}
100
+ it{expect(Zenflow::Query.valid_response?('foo', options: ['bar'])).to eq(false)}
101
+ it{expect(Zenflow::Query.valid_response?('foo', validate: /foo/)).to eq(true)}
102
+ it{expect(Zenflow::Query.valid_response?('foo', validate: /bar/)).to eq(false)}
103
+ it{expect(Zenflow::Query.valid_response?('', required: true)).to eq(false)}
104
+ it{expect(Zenflow::Query.valid_response?('foo', required: true)).to eq(true)}
105
+ it{expect(Zenflow::Query.valid_response?('foo', required: false)).to eq(true)}
106
+ it{expect(Zenflow::Query.valid_response?('', required: false)).to eq(true)}
107
+ end
108
+
109
+ describe '.build_error_message' do
110
+ it{expect(Zenflow::Query.build_error_message('foo')).to match(/not a valid response/)}
111
+ it{expect(Zenflow::Query.build_error_message('foo', error_message: 'stupid response.')).to match(/stupid response/)}
112
+ it{expect(Zenflow::Query.build_error_message('foo', required: true)).to match(/must respond/)}
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,310 @@
1
+ require 'spec_helper'
2
+
3
+ module BranchCommandSpec
4
+
5
+ class TestCommand < Zenflow::BranchCommand
6
+ flow "test"
7
+ branch source: "master"
8
+ branch destination: "production"
9
+ branch deploy: "deploy1"
10
+ branch deploy: "deploy2"
11
+ version :patch
12
+ changelog :rotate
13
+ tag true
14
+ end
15
+
16
+ describe "Zenflow::BranchCommand" do
17
+ describe "#branches" do
18
+ before do
19
+ Zenflow.should_receive(:Log).with("Available test branches:")
20
+ Zenflow::Branch.should_receive(:list).with("test").and_return(["YES"])
21
+ Zenflow.should_receive(:Log).with("* YES", indent: true, color: false)
22
+ end
23
+ it { TestCommand.new.invoke(:branches) }
24
+ end
25
+
26
+ describe "#start" do
27
+ context "when online" do
28
+ before do
29
+ Zenflow.should_receive(:Ask).and_return("new-test-branch")
30
+ Zenflow::Branch.should_receive(:update).with("master")
31
+ Zenflow::Branch.should_receive(:create).with("test/new-test-branch", "master")
32
+ Zenflow::Branch.should_receive(:push).with("test/new-test-branch")
33
+ Zenflow::Branch.should_receive(:track).with("test/new-test-branch")
34
+ end
35
+ it { TestCommand.new.invoke(:start) }
36
+ end
37
+
38
+ context "when offline" do
39
+ before do
40
+ Zenflow.should_receive(:Ask).and_return("new-test-branch")
41
+ Zenflow::Branch.should_receive(:checkout).with("master")
42
+ Zenflow::Branch.should_receive(:create).with("test/new-test-branch", "master")
43
+ end
44
+ it { TestCommand.new.invoke(:start, nil, offline: true) }
45
+ end
46
+
47
+ context "when supplying a name" do
48
+ before do
49
+ Zenflow::Branch.should_receive(:update).with("master")
50
+ Zenflow::Branch.should_receive(:create).with("test/new-test-branch", "master")
51
+ Zenflow::Branch.should_receive(:push).with("test/new-test-branch")
52
+ Zenflow::Branch.should_receive(:track).with("test/new-test-branch")
53
+ end
54
+ it { TestCommand.new.invoke(:start, ["new-test-branch"]) }
55
+ end
56
+
57
+ context "when asking for a name" do
58
+ before do
59
+ $stdin.should_receive(:gets).and_return("new-test-branch\n")
60
+ Zenflow::Branch.should_receive(:update).with("master")
61
+ Zenflow::Branch.should_receive(:create).with("test/new-test-branch", "master")
62
+ Zenflow::Branch.should_receive(:push).with("test/new-test-branch")
63
+ Zenflow::Branch.should_receive(:track).with("test/new-test-branch")
64
+ end
65
+ it { expect(capture(:stdout){ TestCommand.new.invoke(:start) }).to eq(">> Name of the test: ") }
66
+ end
67
+ end
68
+
69
+ describe "#deploy" do
70
+ context "when a project is not deployable" do
71
+ before do
72
+ Zenflow::Branch.should_receive(:current).with("test").and_return("new-test-branch")
73
+ Zenflow::Config.should_receive(:[]).with(:deployable).and_return(false)
74
+ Zenflow.should_receive(:Log).with("This project is not deployable right now", color: :red)
75
+ end
76
+ it { expect{TestCommand.new.invoke(:deploy)}.to raise_error(SystemExit) }
77
+ end
78
+
79
+ context "without running migrations" do
80
+ before do
81
+ Zenflow::Branch.should_receive(:current).with("test").and_return("new-test-branch")
82
+ Zenflow::Config.should_receive(:[]).with(:deployable).and_return(true)
83
+ Zenflow::Branch.should_receive(:update).with("deploy1")
84
+ Zenflow::Branch.should_receive(:update).with("deploy2")
85
+ Zenflow::Branch.should_receive(:merge).with("test/new-test-branch").twice
86
+ Zenflow.should_receive(:Deploy).with("deploy1", {})
87
+ Zenflow.should_receive(:Deploy).with("deploy2", {})
88
+ Zenflow::Branch.should_receive(:checkout).with("test/new-test-branch")
89
+ end
90
+ it { TestCommand.new.invoke(:deploy) }
91
+ end
92
+
93
+ context "when running migrations" do
94
+ before do
95
+ Zenflow::Branch.should_receive(:current).with("test").and_return("new-test-branch")
96
+ Zenflow::Config.should_receive(:[]).with(:deployable).and_return(true)
97
+ Zenflow::Branch.should_receive(:update).with("deploy1")
98
+ Zenflow::Branch.should_receive(:update).with("deploy2")
99
+ Zenflow::Branch.should_receive(:merge).with("test/new-test-branch").twice
100
+ Zenflow.should_receive(:Deploy).with("deploy1", { "migrations" => true })
101
+ Zenflow.should_receive(:Deploy).with("deploy2", { "migrations" => true })
102
+ Zenflow::Branch.should_receive(:checkout).with("test/new-test-branch")
103
+ end
104
+ it { TestCommand.new.invoke(:deploy, [], "migrations" => true) }
105
+ end
106
+ end
107
+
108
+ describe "#update" do
109
+ before do
110
+ Zenflow::Branch.should_receive(:current).with("test").and_return("new-test-branch")
111
+ Zenflow::Branch.should_receive(:update).with("master")
112
+ Zenflow::Branch.should_receive(:checkout).with("test/new-test-branch")
113
+ Zenflow::Branch.should_receive(:merge).with("master")
114
+ end
115
+ it { TestCommand.new.invoke(:update) }
116
+ end
117
+
118
+ describe "#diff" do
119
+ before do
120
+ Zenflow.should_receive(:Log).with("Displaying diff with master")
121
+ Zenflow::Shell.should_receive(:[]).with("git difftool master")
122
+ end
123
+ it { TestCommand.new.invoke(:diff) }
124
+ end
125
+
126
+ describe "#compare" do
127
+ before do
128
+ Zenflow::Branch.should_receive(:current).with("test").and_return("new-test-branch")
129
+ Zenflow.should_receive(:Log).with("Opening GitHub compare view for master...test/new-test-branch")
130
+ Zenflow::Repo.should_receive(:slug).and_return("test-repo")
131
+ Zenflow::Shell.should_receive(:[]).with("open https://github.com/test-repo/compare/master...test/new-test-branch")
132
+ end
133
+ it { TestCommand.new.invoke(:compare) }
134
+ end
135
+
136
+ describe "#review" do
137
+ context "when pull request is found" do
138
+ before do
139
+ Zenflow::Branch.should_receive(:current).with("test").and_return("new-test-branch")
140
+ Zenflow::PullRequest.should_receive(:find_by_ref).with("test/new-test-branch").and_return({ html_url: "URL"})
141
+ Zenflow.should_receive(:Log).with("A pull request for test/new-test-branch already exists", color: :red)
142
+ Zenflow.should_receive(:Log).with("URL", indent: true, color: false)
143
+ end
144
+ it { expect{TestCommand.new.invoke(:review)}.to raise_error(SystemExit) }
145
+ end
146
+
147
+ context "with new pull request" do
148
+ before do
149
+ Zenflow::Branch.should_receive(:current).with("test").and_return("new-test-branch")
150
+ Zenflow::PullRequest.should_receive(:find_by_ref).with("test/new-test-branch").and_return(false)
151
+ end
152
+
153
+ context "with valid request" do
154
+ before do
155
+ Zenflow.should_receive(:Ask).with("Describe this test:", required: true).and_return("A great test")
156
+ pull = double(valid?: true)
157
+ pull.stub(:[]).with("html_url").and_return("URL")
158
+ Zenflow::PullRequest.should_receive(:create).with(
159
+ base: "master",
160
+ head: "test/new-test-branch",
161
+ title: "test: new-test-branch",
162
+ body: "A great test"
163
+ ).and_return(pull)
164
+ Zenflow.should_receive(:Log).with("Pull request was created!")
165
+ Zenflow.should_receive(:Log).with("URL", indent: true, color: false)
166
+ Zenflow::Shell.should_receive(:[]).with("open URL")
167
+ end
168
+ it { TestCommand.new.invoke(:review) }
169
+ end
170
+
171
+ context "with invalid request" do
172
+ let(:pull){ double(valid?: false) }
173
+
174
+ before do
175
+ Zenflow.should_receive(:Ask).with("Describe this test:", required: true).and_return("A great test")
176
+ Zenflow::PullRequest.should_receive(:create).with(
177
+ base: "master",
178
+ head: "test/new-test-branch",
179
+ title: "test: new-test-branch",
180
+ body: "A great test"
181
+ ).and_return(pull)
182
+ Zenflow.should_receive(:Log).with("There was a problem creating the pull request:", color: :red)
183
+ end
184
+
185
+ it "displays errors" do
186
+ pull.stub(:[]).with("errors").and_return([{"message" => "ERROR"},{"message" => "ERROR"}])
187
+ Zenflow.should_receive(:Log).with("* ERROR", indent: true, color: :red).twice
188
+ TestCommand.new.invoke(:review)
189
+ end
190
+
191
+ it "displays an error message" do
192
+ pull.stub(:[]).with("errors")
193
+ pull.stub(:[]).with("message").and_return("ERROR")
194
+ Zenflow.should_receive(:Log).with("* ERROR", indent: true, color: :red)
195
+ TestCommand.new.invoke(:review)
196
+ end
197
+
198
+ it "handles unexpected failure" do
199
+ pull.stub(:[]).with("errors")
200
+ pull.stub(:[]).with("message")
201
+ Zenflow.should_receive(:Log).with(" * unexpected failure, both 'errors' and 'message' were empty in the response")
202
+ TestCommand.new.invoke(:review)
203
+ end
204
+ end
205
+ end
206
+ end
207
+
208
+ describe "#abort" do
209
+ let(:branch_name){"test/new-test-branch"}
210
+ before {
211
+ Zenflow::Branch.should_receive(:current).with("test").and_return("new-test-branch")
212
+ Zenflow::Branch.should_receive(:checkout).with("master")
213
+ }
214
+
215
+ context "when online" do
216
+ before do
217
+ Zenflow::Branch.should_receive(:delete_remote).with(branch_name)
218
+ Zenflow::Branch.should_receive(:delete_local).with(branch_name, force: true)
219
+ end
220
+ it { TestCommand.new.invoke(:abort) }
221
+ end
222
+
223
+ context "when offline" do
224
+ before do
225
+ Zenflow::Branch.should_receive(:delete_local).with(branch_name, force: true)
226
+ end
227
+ it { TestCommand.new.invoke(:abort, [], offline: true) }
228
+ end
229
+ end
230
+
231
+ describe "#finish" do
232
+ before do
233
+ Zenflow::Branch.should_receive(:current).with("test").and_return("new-test-branch")
234
+ end
235
+
236
+ context "with confirmations" do
237
+ it "without deployment to staging" do
238
+ Zenflow::Config.should_receive(:[]).with(:confirm_staging).and_return(true)
239
+ Zenflow.should_receive(:Ask).with("Has this been tested in a staging environment first?", options: ["Y", "n"], default: "Y").and_return("n")
240
+ Zenflow.should_receive(:Log).with("Sorry, deploy to a staging environment first", color: :red)
241
+ expect{TestCommand.new.invoke(:finish)}.to raise_error(SystemExit)
242
+ end
243
+
244
+ it "without review" do
245
+ Zenflow::Config.should_receive(:[]).with(:confirm_staging).and_return(true)
246
+ Zenflow::Config.should_receive(:[]).with(:confirm_review).and_return(true)
247
+ Zenflow.should_receive(:Ask).with("Has this been tested in a staging environment first?", options: ["Y", "n"], default: "Y").and_return("y")
248
+ Zenflow.should_receive(:Ask).with("Has this been code reviewed yet?", options: ["Y", "n"], default: "Y").and_return("n")
249
+ Zenflow.should_receive(:Log).with("Please have someone look at this first", color: :red)
250
+ expect{TestCommand.new.invoke(:finish)}.to raise_error(SystemExit)
251
+ end
252
+ end
253
+
254
+ context "without confirmations" do
255
+ before do
256
+ Zenflow::Config.should_receive(:[]).with(:confirm_staging).and_return(false)
257
+ Zenflow::Config.should_receive(:[]).with(:confirm_review).and_return(false)
258
+ end
259
+
260
+ context "when online" do
261
+ before do
262
+ Zenflow::Branch.should_receive(:update).with("production")
263
+ Zenflow::Branch.should_receive(:checkout).with("test/new-test-branch")
264
+ Zenflow::Branch.should_receive(:merge).with("production")
265
+
266
+ Zenflow::Version.should_receive(:update).with(:patch)
267
+
268
+ Zenflow::Changelog.should_receive(:update).with(rotate: true, name: "new-test-branch").and_return("YES")
269
+
270
+ Zenflow::Branch.should_receive(:checkout).with("master")
271
+ Zenflow::Branch.should_receive(:merge).with("test/new-test-branch")
272
+ Zenflow::Branch.should_receive(:push).with("master")
273
+ Zenflow::Branch.should_receive(:checkout).with("production")
274
+ Zenflow::Branch.should_receive(:merge).with("test/new-test-branch")
275
+ Zenflow::Branch.should_receive(:push).with("production")
276
+
277
+ Zenflow::Branch.should_receive(:tag).with(Zenflow::Version.current.to_s, "YES")
278
+ Zenflow::Branch.should_receive(:push).with(:tags)
279
+
280
+ Zenflow::Branch.should_receive(:delete_remote).with("test/new-test-branch")
281
+ Zenflow::Branch.should_receive(:delete_local).with("test/new-test-branch", force: true)
282
+ end
283
+ it { TestCommand.new.invoke(:finish) }
284
+ end
285
+
286
+ context "when offline" do
287
+ before do
288
+ Zenflow::Branch.should_receive(:checkout).with("test/new-test-branch")
289
+ Zenflow::Branch.should_receive(:merge).with("production")
290
+
291
+ Zenflow::Version.should_receive(:update).with(:patch)
292
+
293
+ Zenflow::Changelog.should_receive(:update).with(rotate: true, name: "new-test-branch").and_return("YES")
294
+
295
+ Zenflow::Branch.should_receive(:checkout).with("master")
296
+ Zenflow::Branch.should_receive(:merge).with("test/new-test-branch")
297
+ Zenflow::Branch.should_receive(:checkout).with("production")
298
+ Zenflow::Branch.should_receive(:merge).with("test/new-test-branch")
299
+
300
+ Zenflow::Branch.should_receive(:tag).with(Zenflow::Version.current.to_s, "YES")
301
+
302
+ Zenflow::Branch.should_receive(:delete_local).with("test/new-test-branch", force: true)
303
+ end
304
+ it { TestCommand.new.invoke(:finish, [], offline: true) }
305
+ end
306
+ end
307
+ end
308
+ end
309
+
310
+ end