pivotal-integration 1.6.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +15 -0
  2. data/LICENSE +202 -0
  3. data/NOTICE +2 -0
  4. data/README.md +331 -0
  5. data/bin/pivotal +81 -0
  6. data/lib/pivotal-integration/command/assign.rb +50 -0
  7. data/lib/pivotal-integration/command/base.rb +63 -0
  8. data/lib/pivotal-integration/command/command.rb +20 -0
  9. data/lib/pivotal-integration/command/comment.rb +31 -0
  10. data/lib/pivotal-integration/command/configuration.rb +129 -0
  11. data/lib/pivotal-integration/command/estimate.rb +53 -0
  12. data/lib/pivotal-integration/command/finish.rb +50 -0
  13. data/lib/pivotal-integration/command/info.rb +30 -0
  14. data/lib/pivotal-integration/command/label.rb +33 -0
  15. data/lib/pivotal-integration/command/mark.rb +44 -0
  16. data/lib/pivotal-integration/command/new.rb +52 -0
  17. data/lib/pivotal-integration/command/open.rb +31 -0
  18. data/lib/pivotal-integration/command/prepare-commit-msg.sh +26 -0
  19. data/lib/pivotal-integration/command/release.rb +54 -0
  20. data/lib/pivotal-integration/command/start.rb +82 -0
  21. data/lib/pivotal-integration/command/switch.rb +44 -0
  22. data/lib/pivotal-integration/util/git.rb +280 -0
  23. data/lib/pivotal-integration/util/label.rb +72 -0
  24. data/lib/pivotal-integration/util/shell.rb +36 -0
  25. data/lib/pivotal-integration/util/story.rb +170 -0
  26. data/lib/pivotal-integration/util/util.rb +20 -0
  27. data/lib/pivotal-integration/version-update/gradle.rb +64 -0
  28. data/lib/pivotal-integration/version-update/version_update.rb +20 -0
  29. data/lib/pivotal_integration.rb +18 -0
  30. data/spec/git-pivotal-tracker-integration/command/assign_spec.rb +55 -0
  31. data/spec/git-pivotal-tracker-integration/command/base_spec.rb +38 -0
  32. data/spec/git-pivotal-tracker-integration/command/configuration_spec.rb +119 -0
  33. data/spec/git-pivotal-tracker-integration/command/finish_spec.rb +45 -0
  34. data/spec/git-pivotal-tracker-integration/command/label_spec.rb +44 -0
  35. data/spec/git-pivotal-tracker-integration/command/mark_spec.rb +49 -0
  36. data/spec/git-pivotal-tracker-integration/command/release_spec.rb +57 -0
  37. data/spec/git-pivotal-tracker-integration/command/start_spec.rb +55 -0
  38. data/spec/git-pivotal-tracker-integration/util/git_spec.rb +235 -0
  39. data/spec/git-pivotal-tracker-integration/util/label_spec.rb +193 -0
  40. data/spec/git-pivotal-tracker-integration/util/shell_spec.rb +52 -0
  41. data/spec/git-pivotal-tracker-integration/util/story_spec.rb +158 -0
  42. data/spec/git-pivotal-tracker-integration/version-update/gradle_spec.rb +74 -0
  43. metadata +241 -0
@@ -0,0 +1,235 @@
1
+ # Git Pivotal Tracker Integration
2
+ # Copyright (c) 2013 the original author or authors.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'spec_helper'
17
+ require 'git-pivotal-tracker-integration/util/git'
18
+ require 'git-pivotal-tracker-integration/util/shell'
19
+
20
+ describe PivotalIntegration::Util::Git do
21
+
22
+ before do
23
+ $stdout = StringIO.new
24
+ $stderr = StringIO.new
25
+ end
26
+
27
+ it 'should return the current branch name' do
28
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git branch').and_return(" master\n * dev_branch")
29
+
30
+ current_branch = PivotalIntegration::Util::Git.branch_name
31
+
32
+ expect(current_branch).to eq('dev_branch')
33
+ end
34
+
35
+ it 'should return the repository root' do
36
+ Dir.mktmpdir do |root|
37
+ child_directory = File.expand_path 'child', root
38
+ Dir.mkdir child_directory
39
+
40
+ git_directory = File.expand_path '.git', root
41
+ Dir.mkdir git_directory
42
+
43
+ Dir.should_receive(:pwd).and_return(child_directory)
44
+
45
+ repository_root = PivotalIntegration::Util::Git.repository_root
46
+
47
+ expect(repository_root).to eq(root)
48
+ end
49
+ end
50
+
51
+ it 'should raise an error there is no repository root' do
52
+ Dir.mktmpdir do |root|
53
+ child_directory = File.expand_path 'child', root
54
+ Dir.mkdir child_directory
55
+
56
+ Dir.should_receive(:pwd).and_return(child_directory)
57
+
58
+ expect { PivotalIntegration::Util::Git.repository_root }.to raise_error
59
+ end
60
+ end
61
+
62
+ it 'should get configuration when :branch scope is specified' do
63
+ PivotalIntegration::Util::Git.should_receive(:branch_name).and_return('test_branch_name')
64
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git config branch.test_branch_name.test_key', false).and_return('test_value')
65
+
66
+ value = PivotalIntegration::Util::Git.get_config 'test_key', :branch
67
+
68
+ expect(value).to eq('test_value')
69
+ end
70
+
71
+ it 'should get configuration when :inherited scope is specified' do
72
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git config test_key', false).and_return('test_value')
73
+
74
+ value = PivotalIntegration::Util::Git.get_config 'test_key', :inherited
75
+
76
+ expect(value).to eq('test_value')
77
+ end
78
+
79
+ it 'should raise an error when an unknown scope is specified (get)' do
80
+ expect { PivotalIntegration::Util::Git.get_config 'test_key', :unknown }.to raise_error
81
+ end
82
+
83
+ it 'should set configuration when :branch scope is specified' do
84
+ PivotalIntegration::Util::Git.should_receive(:branch_name).and_return('test_branch_name')
85
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git config --local branch.test_branch_name.test_key test_value')
86
+
87
+ PivotalIntegration::Util::Git.set_config 'test_key', 'test_value', :branch
88
+ end
89
+
90
+ it 'should set configuration when :global scope is specified' do
91
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git config --global test_key test_value')
92
+
93
+ PivotalIntegration::Util::Git.set_config 'test_key', 'test_value', :global
94
+ end
95
+
96
+ it 'should set configuration when :local scope is specified' do
97
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git config --local test_key test_value')
98
+
99
+ PivotalIntegration::Util::Git.set_config 'test_key', 'test_value', :local
100
+ end
101
+
102
+ it 'should raise an error when an unknown scope is specified (set)' do
103
+ expect { PivotalIntegration::Util::Git.set_config 'test_key', 'test_value', :unknown }.to raise_error
104
+ end
105
+
106
+ it 'should create a branch and set the root_branch and root_remote properties on it' do
107
+ PivotalIntegration::Util::Git.should_receive(:branch_name).and_return('master')
108
+ PivotalIntegration::Util::Git.should_receive(:get_config).with('remote', :branch).and_return('origin')
109
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git pull --quiet --ff-only')
110
+ PivotalIntegration::Util::Shell.should_receive(:exec).and_return('git checkout --quiet -b dev_branch')
111
+ PivotalIntegration::Util::Git.should_receive(:set_config).with('root-branch', 'master', :branch)
112
+ PivotalIntegration::Util::Git.should_receive(:set_config).with('root-remote', 'origin', :branch)
113
+
114
+ PivotalIntegration::Util::Git.create_branch 'dev_branch'
115
+ end
116
+
117
+ it 'should not add a hook if it already exists' do
118
+ Dir.mktmpdir do |root|
119
+ PivotalIntegration::Util::Git.should_receive(:repository_root).and_return(root)
120
+ hook = "#{root}/.git/hooks/prepare-commit-msg"
121
+ File.should_receive(:exist?).with(hook).and_return(true)
122
+
123
+ PivotalIntegration::Util::Git.add_hook 'prepare-commit-msg', __FILE__
124
+
125
+ File.should_receive(:exist?).and_call_original
126
+ expect(File.exist?(hook)).to be_false
127
+ end
128
+ end
129
+
130
+ it 'should add a hook if it does not exist' do
131
+ Dir.mktmpdir do |root|
132
+ PivotalIntegration::Util::Git.should_receive(:repository_root).and_return(root)
133
+ hook = "#{root}/.git/hooks/prepare-commit-msg"
134
+ File.should_receive(:exist?).with(hook).and_return(false)
135
+
136
+ PivotalIntegration::Util::Git.add_hook 'prepare-commit-msg', __FILE__
137
+
138
+ File.should_receive(:exist?).and_call_original
139
+ expect(File.exist?(hook)).to be_true
140
+ end
141
+ end
142
+
143
+ it 'should add a hook if it already exists and overwrite is true' do
144
+ Dir.mktmpdir do |root|
145
+ PivotalIntegration::Util::Git.should_receive(:repository_root).and_return(root)
146
+ hook = "#{root}/.git/hooks/prepare-commit-msg"
147
+
148
+ PivotalIntegration::Util::Git.add_hook 'prepare-commit-msg', __FILE__, true
149
+
150
+ File.should_receive(:exist?).and_call_original
151
+ expect(File.exist?(hook)).to be_true
152
+ end
153
+ end
154
+
155
+ it 'should fail if root tip and common_ancestor do not match' do
156
+ PivotalIntegration::Util::Git.should_receive(:branch_name).and_return('development_branch')
157
+ PivotalIntegration::Util::Git.should_receive(:get_config).with('root-branch', :branch).and_return('master')
158
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git checkout --quiet master')
159
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git pull --quiet --ff-only')
160
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git checkout --quiet development_branch')
161
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git rev-parse master').and_return('root_tip')
162
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git merge-base master development_branch').and_return('common_ancestor')
163
+
164
+ lambda { PivotalIntegration::Util::Git.trivial_merge? }.should raise_error(SystemExit)
165
+
166
+ expect($stderr.string).to match(/FAIL/)
167
+ end
168
+
169
+ it 'should pass if root tip and common ancestor match' do
170
+ PivotalIntegration::Util::Git.should_receive(:branch_name).and_return('development_branch')
171
+ PivotalIntegration::Util::Git.should_receive(:get_config).with('root-branch', :branch).and_return('master')
172
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git checkout --quiet master')
173
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git pull --quiet --ff-only')
174
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git checkout --quiet development_branch')
175
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git rev-parse master').and_return('HEAD')
176
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git merge-base master development_branch').and_return('HEAD')
177
+
178
+ PivotalIntegration::Util::Git.trivial_merge?
179
+
180
+ expect($stdout.string).to match(/OK/)
181
+ end
182
+
183
+ it 'should merge and delete branches' do
184
+ PivotalIntegration::Util::Git.should_receive(:branch_name).and_return('development_branch')
185
+ PivotalIntegration::Util::Git.should_receive(:get_config).with('root-branch', :branch).and_return('master')
186
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git checkout --quiet master')
187
+ PivotalIntegration::Util::Shell.should_receive(:exec).with("git merge --quiet --no-ff -m \"Merge development_branch to master\n\n[Completes #12345678]\" development_branch")
188
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git branch --quiet -D development_branch')
189
+
190
+ PivotalIntegration::Util::Git.merge PivotalTracker::Story.new(:id => 12345678), nil, nil
191
+ end
192
+
193
+ it 'should suppress Completes statement' do
194
+ PivotalIntegration::Util::Git.should_receive(:branch_name).and_return('development_branch')
195
+ PivotalIntegration::Util::Git.should_receive(:get_config).with('root-branch', :branch).and_return('master')
196
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git checkout --quiet master')
197
+ PivotalIntegration::Util::Shell.should_receive(:exec).with("git merge --quiet --no-ff -m \"Merge development_branch to master\n\n[#12345678]\" development_branch")
198
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git branch --quiet -D development_branch')
199
+
200
+ PivotalIntegration::Util::Git.merge PivotalTracker::Story.new(:id => 12345678), true, nil
201
+ end
202
+
203
+ it 'should push changes without refs' do
204
+ PivotalIntegration::Util::Git.should_receive(:get_config).with('remote', :branch).and_return('origin')
205
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git push --quiet origin ')
206
+
207
+ PivotalIntegration::Util::Git.push
208
+ end
209
+
210
+ it 'should push changes with refs' do
211
+ PivotalIntegration::Util::Git.should_receive(:get_config).with('remote', :branch).and_return('origin')
212
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git push --quiet origin foo bar')
213
+
214
+ PivotalIntegration::Util::Git.push 'foo', 'bar'
215
+ end
216
+
217
+ it 'should create a commit' do
218
+ story = PivotalTracker::Story.new(:id => 123456789)
219
+ PivotalIntegration::Util::Shell.should_receive(:exec).with("git commit --quiet --all --allow-empty --message \"test_message\n\n[#123456789]\"")
220
+
221
+ PivotalIntegration::Util::Git.create_commit 'test_message', story
222
+ end
223
+
224
+ it 'should create a release tag' do
225
+ story = PivotalTracker::Story.new(:id => 123456789)
226
+ PivotalIntegration::Util::Git.should_receive(:branch_name).and_return('master')
227
+ PivotalIntegration::Util::Git.should_receive(:create_branch).with('pivotal-tracker-release', false)
228
+ PivotalIntegration::Util::Git.should_receive(:create_commit).with('1.0.0.RELEASE Release', story)
229
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git tag v1.0.0.RELEASE')
230
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git checkout --quiet master')
231
+ PivotalIntegration::Util::Shell.should_receive(:exec).with('git branch --quiet -D pivotal-tracker-release')
232
+
233
+ PivotalIntegration::Util::Git.create_release_tag '1.0.0.RELEASE', story
234
+ end
235
+ end
@@ -0,0 +1,193 @@
1
+ # Git Pivotal Tracker Integration
2
+ # Copyright (c) 2013 the original author or authors.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'spec_helper'
17
+ require 'git-pivotal-tracker-integration/util/label'
18
+ require 'pivotal-tracker'
19
+
20
+ describe PivotalIntegration::Util::Label do
21
+
22
+ before do
23
+ $stdout = StringIO.new
24
+ $stderr = StringIO.new
25
+
26
+ @project = double('project')
27
+ @stories = double('stories')
28
+ @story = double('story')
29
+ @menu = double('menu')
30
+ end
31
+
32
+ it 'should add labels to story' do
33
+ old_labels = 'other_label'
34
+ @story.should_receive(:labels).and_return(old_labels)
35
+ @story.should_receive(:update).with(:labels => ["other_label", "on_qa"]).and_return(true)
36
+ @story.should_receive(:name)
37
+
38
+ PivotalIntegration::Util::Label.add(@story, 'on_qa')
39
+ end
40
+
41
+ it 'should add unique labels to story' do
42
+ PivotalTracker::Project.should_receive(:find).and_return(@project)
43
+ project_id = 123
44
+ other_story = double(:other_story)
45
+ @story.should_receive(:project_id).and_return(project_id)
46
+ @project.should_receive(:stories).and_return(@stories)
47
+ @stories.should_receive(:all).and_return([@story, other_story])
48
+ @story.should_receive(:name).exactly(4).times.and_return('name')
49
+ other_story.should_receive(:name).exactly(2).times.and_return('other_name')
50
+ @story.should_receive(:labels).and_return('other_label')
51
+ other_story.should_receive(:labels).exactly(3).times.and_return('on_qa')
52
+ other_story.should_receive(:update).and_return(true)
53
+ @story.should_receive(:update).with(:labels => ["other_label", "on_qa"]).and_return(true)
54
+ PivotalIntegration::Util::Label.once(@story, 'on_qa')
55
+ end
56
+
57
+ it 'should abort when cannot add labels to story' do
58
+ old_labels = 'other_label'
59
+ @story.should_receive(:labels).and_return(old_labels)
60
+ @story.should_receive(:update).with(:labels => ["other_label", "on_qa"]).and_return(false)
61
+ lambda { PivotalIntegration::Util::Label.add(@story, 'on_qa') }.should raise_error SystemExit
62
+ end
63
+
64
+ it 'should abort when cannot remove labels from story' do
65
+ old_labels = 'other_label,on_qa'
66
+ @story.should_receive(:labels).and_return(old_labels)
67
+ @story.should_receive(:update).with(:labels => ["other_label"]).and_return(false)
68
+ lambda { PivotalIntegration::Util::Label.remove(@story, 'on_qa') }.should raise_error SystemExit
69
+ end
70
+
71
+
72
+
73
+
74
+
75
+
76
+
77
+
78
+
79
+
80
+ it 'should pretty print story labels' do
81
+ @story.should_receive(:labels).and_return('label1,label2')
82
+ PivotalIntegration::Util::Label.list @story
83
+ end
84
+
85
+ it 'should not pretty print description or notes if there are none (empty)' do
86
+ story = double('story')
87
+ story.should_receive(:name)
88
+ story.should_receive(:description)
89
+ PivotalTracker::Note.should_receive(:all).and_return([])
90
+
91
+ PivotalIntegration::Util::Story.pretty_print story
92
+
93
+ expect($stdout.string).to eq(
94
+ " Title: \n" +
95
+ "\n")
96
+ end
97
+
98
+ it 'should not pretty print description or notes if there are none (nil)' do
99
+ story = double('story')
100
+ story.should_receive(:name)
101
+ story.should_receive(:description).and_return('')
102
+ PivotalTracker::Note.should_receive(:all).and_return([])
103
+
104
+ PivotalIntegration::Util::Story.pretty_print story
105
+
106
+ expect($stdout.string).to eq(
107
+ " Title: \n" +
108
+ "\n")
109
+ end
110
+
111
+ it 'should assign owner to story and notify about success' do
112
+ story = double('story')
113
+ username = 'User Name'
114
+ story.should_receive(:update).with({ :owned_by => username }).and_return(true)
115
+
116
+ PivotalIntegration::Util::Story.assign story, username
117
+
118
+ expect($stdout.string).to eq(
119
+ "Story assigned to #{username}" +
120
+ "\n")
121
+ end
122
+
123
+ it 'should change story state and notify about success' do
124
+ story = double('story')
125
+ state = 'finished'
126
+ story.should_receive(:update).with({ :current_state => state }).and_return(true)
127
+
128
+ PivotalIntegration::Util::Story.mark story, state
129
+
130
+ expect($stdout.string).to eq(
131
+ "Changed state to #{state}" +
132
+ "\n")
133
+ end
134
+
135
+ it 'should select a story directly if the filter is a number' do
136
+ @project.should_receive(:stories).and_return(@stories)
137
+ @stories.should_receive(:find).with(12345678).and_return(@story)
138
+
139
+ story = PivotalIntegration::Util::Story.select_story @project, '12345678'
140
+
141
+ expect(story).to be(@story)
142
+ end
143
+
144
+ it 'should select a story if the result of the query is a single story' do
145
+ @project.should_receive(:stories).and_return(@stories)
146
+ @stories.should_receive(:all).with(
147
+ :current_state => %w(rejected unstarted unscheduled),
148
+ :story_type => 'release'
149
+ ).and_return([@story])
150
+ @story.should_receive(:owned_by)
151
+ story = PivotalIntegration::Util::Story.select_story @project, 'release', 1
152
+
153
+ expect(story).to be(@story)
154
+ end
155
+
156
+ it 'should prompt the user for a story if the result of the query is more than a single story' do
157
+ @project.should_receive(:stories).and_return(@stories)
158
+ @stories.should_receive(:all).with(
159
+ :current_state => %w(rejected unstarted unscheduled),
160
+ :story_type => 'feature'
161
+ ).and_return([
162
+ PivotalTracker::Story.new(:name => 'name-1'),
163
+ PivotalTracker::Story.new(:name => 'name-2')
164
+ ])
165
+ @menu.should_receive(:prompt=)
166
+ @menu.should_receive(:choice).with('name-1')
167
+ @menu.should_receive(:choice).with('name-2')
168
+ PivotalIntegration::Util::Story.should_receive(:choose) { |&arg| arg.call @menu }.and_return(@story)
169
+
170
+ story = PivotalIntegration::Util::Story.select_story @project, 'feature'
171
+
172
+ expect(story).to be(@story)
173
+ end
174
+
175
+ it 'should prompt the user with the story type if no filter is specified' do
176
+ @project.should_receive(:stories).and_return(@stories)
177
+ @stories.should_receive(:all).with(
178
+ :current_state => %w(rejected unstarted unscheduled)
179
+ ).and_return([
180
+ PivotalTracker::Story.new(:story_type => 'chore', :name => 'name-1'),
181
+ PivotalTracker::Story.new(:story_type => 'bug', :name => 'name-2')
182
+ ])
183
+ @menu.should_receive(:prompt=)
184
+ @menu.should_receive(:choice).with('CHORE name-1')
185
+ @menu.should_receive(:choice).with('BUG name-2')
186
+ PivotalIntegration::Util::Story.should_receive(:choose) { |&arg| arg.call @menu }.and_return(@story)
187
+
188
+ story = PivotalIntegration::Util::Story.select_story @project
189
+
190
+ expect(story).to be(@story)
191
+ end
192
+
193
+ end
@@ -0,0 +1,52 @@
1
+ # Git Pivotal Tracker Integration
2
+ # Copyright (c) 2013 the original author or authors.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'spec_helper'
17
+ require 'git-pivotal-tracker-integration/util/shell'
18
+
19
+ describe PivotalIntegration::Util::Shell do
20
+
21
+ before do
22
+ $stdout = StringIO.new
23
+ $stderr = StringIO.new
24
+ end
25
+
26
+ it 'should return result when exit code is 0' do
27
+ PivotalIntegration::Util::Shell.should_receive(:`).with('test_command').and_return('test_result')
28
+ $?.should_receive(:exitstatus).and_return(0)
29
+
30
+ result = PivotalIntegration::Util::Shell.exec 'test_command'
31
+
32
+ expect(result).to eq('test_result')
33
+ end
34
+
35
+ it "should abort with 'FAIL' when the exit code is not 0" do
36
+ PivotalIntegration::Util::Shell.should_receive(:`).with('test_command')
37
+ $?.should_receive(:exitstatus).and_return(-1)
38
+
39
+ lambda { PivotalIntegration::Util::Shell.exec 'test_command' }.should raise_error(SystemExit)
40
+
41
+ expect($stderr.string).to match(/FAIL/)
42
+ end
43
+
44
+ it 'should return result when the exit code is not 0 and told not to abort on failure' do
45
+ PivotalIntegration::Util::Shell.should_receive(:`).with('test_command')
46
+ $?.should_receive(:exitstatus).and_return(-1)
47
+
48
+ PivotalIntegration::Util::Shell.exec 'test_command', false
49
+ end
50
+
51
+
52
+ end
@@ -0,0 +1,158 @@
1
+ # Git Pivotal Tracker Integration
2
+ # Copyright (c) 2013 the original author or authors.
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'spec_helper'
17
+ require 'git-pivotal-tracker-integration/util/story'
18
+ require 'pivotal-tracker'
19
+
20
+ describe PivotalIntegration::Util::Story do
21
+
22
+ before do
23
+ $stdout = StringIO.new
24
+ $stderr = StringIO.new
25
+
26
+ @project = double('project')
27
+ @stories = double('stories')
28
+ @story = double('story')
29
+ @menu = double('menu')
30
+ end
31
+
32
+ it 'should pretty print story information' do
33
+ story = double('story')
34
+ story.should_receive(:name)
35
+ story.should_receive(:description).and_return("description-1\ndescription-2")
36
+ PivotalTracker::Note.should_receive(:all).and_return([
37
+ PivotalTracker::Note.new(:noted_at => Date.new, :text => 'note-1')
38
+ ])
39
+
40
+ PivotalIntegration::Util::Story.pretty_print story
41
+
42
+ expect($stdout.string).to eq(
43
+ " Title: \n" +
44
+ "Description: description-1\n" +
45
+ " description-2\n" +
46
+ " Note 1: note-1\n" +
47
+ "\n")
48
+ end
49
+
50
+ it 'should not pretty print description or notes if there are none (empty)' do
51
+ story = double('story')
52
+ story.should_receive(:name)
53
+ story.should_receive(:description)
54
+ PivotalTracker::Note.should_receive(:all).and_return([])
55
+
56
+ PivotalIntegration::Util::Story.pretty_print story
57
+
58
+ expect($stdout.string).to eq(
59
+ " Title: \n" +
60
+ "\n")
61
+ end
62
+
63
+ it 'should not pretty print description or notes if there are none (nil)' do
64
+ story = double('story')
65
+ story.should_receive(:name)
66
+ story.should_receive(:description).and_return('')
67
+ PivotalTracker::Note.should_receive(:all).and_return([])
68
+
69
+ PivotalIntegration::Util::Story.pretty_print story
70
+
71
+ expect($stdout.string).to eq(
72
+ " Title: \n" +
73
+ "\n")
74
+ end
75
+
76
+ it 'should assign owner to story and notify about success' do
77
+ story = double('story')
78
+ username = 'User Name'
79
+ story.should_receive(:update).with({ :owned_by => username }).and_return(true)
80
+
81
+ PivotalIntegration::Util::Story.assign story, username
82
+
83
+ expect($stdout.string).to eq(
84
+ "Story assigned to #{username}" +
85
+ "\n")
86
+ end
87
+
88
+ it 'should change story state and notify about success' do
89
+ story = double('story')
90
+ state = 'finished'
91
+ story.should_receive(:update).with({ :current_state => state }).and_return(true)
92
+
93
+ PivotalIntegration::Util::Story.mark story, state
94
+
95
+ expect($stdout.string).to eq(
96
+ "Changed state to #{state}" +
97
+ "\n")
98
+ end
99
+
100
+ it 'should select a story directly if the filter is a number' do
101
+ @project.should_receive(:stories).and_return(@stories)
102
+ @stories.should_receive(:find).with(12345678).and_return(@story)
103
+
104
+ story = PivotalIntegration::Util::Story.select_story @project, '12345678'
105
+
106
+ expect(story).to be(@story)
107
+ end
108
+
109
+ it 'should select a story if the result of the query is a single story' do
110
+ @project.should_receive(:stories).and_return(@stories)
111
+ @stories.should_receive(:all).with(
112
+ :current_state => %w(rejected unstarted unscheduled),
113
+ :story_type => 'release'
114
+ ).and_return([@story])
115
+ @story.should_receive(:owned_by)
116
+ story = PivotalIntegration::Util::Story.select_story @project, 'release', 1
117
+
118
+ expect(story).to be(@story)
119
+ end
120
+
121
+ it 'should prompt the user for a story if the result of the query is more than a single story' do
122
+ @project.should_receive(:stories).and_return(@stories)
123
+ @stories.should_receive(:all).with(
124
+ :current_state => %w(rejected unstarted unscheduled),
125
+ :story_type => 'feature'
126
+ ).and_return([
127
+ PivotalTracker::Story.new(:name => 'name-1'),
128
+ PivotalTracker::Story.new(:name => 'name-2')
129
+ ])
130
+ @menu.should_receive(:prompt=)
131
+ @menu.should_receive(:choice).with('name-1')
132
+ @menu.should_receive(:choice).with('name-2')
133
+ PivotalIntegration::Util::Story.should_receive(:choose) { |&arg| arg.call @menu }.and_return(@story)
134
+
135
+ story = PivotalIntegration::Util::Story.select_story @project, 'feature'
136
+
137
+ expect(story).to be(@story)
138
+ end
139
+
140
+ it 'should prompt the user with the story type if no filter is specified' do
141
+ @project.should_receive(:stories).and_return(@stories)
142
+ @stories.should_receive(:all).with(
143
+ :current_state => %w(rejected unstarted unscheduled)
144
+ ).and_return([
145
+ PivotalTracker::Story.new(:story_type => 'chore', :name => 'name-1'),
146
+ PivotalTracker::Story.new(:story_type => 'bug', :name => 'name-2')
147
+ ])
148
+ @menu.should_receive(:prompt=)
149
+ @menu.should_receive(:choice).with('CHORE name-1')
150
+ @menu.should_receive(:choice).with('BUG name-2')
151
+ PivotalIntegration::Util::Story.should_receive(:choose) { |&arg| arg.call @menu }.and_return(@story)
152
+
153
+ story = PivotalIntegration::Util::Story.select_story @project
154
+
155
+ expect(story).to be(@story)
156
+ end
157
+
158
+ end