caperoma 0.1.0 → 4.0.1

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 (85) hide show
  1. checksums.yaml +5 -5
  2. data/.ruby-version +1 -0
  3. data/Capefile +48 -0
  4. data/Capefile.template +48 -0
  5. data/Capefile.test +20 -0
  6. data/Gemfile +25 -10
  7. data/Gemfile.lock +196 -77
  8. data/HELP +321 -0
  9. data/README.md +528 -0
  10. data/Rakefile +73 -18
  11. data/VERSION +1 -1
  12. data/bin/caperoma +47 -11
  13. data/caperoma.gemspec +144 -45
  14. data/config/crontab +10 -0
  15. data/config/schedule.rb +21 -0
  16. data/lib/caperoma.rb +409 -9
  17. data/lib/caperoma/models/account.rb +47 -0
  18. data/lib/caperoma/models/application_record.rb +5 -0
  19. data/lib/caperoma/models/branch.rb +6 -0
  20. data/lib/caperoma/models/project.rb +14 -0
  21. data/lib/caperoma/models/property.rb +5 -0
  22. data/lib/caperoma/models/report.rb +177 -0
  23. data/lib/caperoma/models/report_recipient.rb +6 -0
  24. data/lib/caperoma/models/reports/daily_report.rb +23 -0
  25. data/lib/caperoma/models/reports/retrospective_report.rb +19 -0
  26. data/lib/caperoma/models/reports/three_day_report.rb +19 -0
  27. data/lib/caperoma/models/task.rb +368 -0
  28. data/lib/caperoma/models/tasks/bug.rb +36 -0
  29. data/lib/caperoma/models/tasks/chore.rb +40 -0
  30. data/lib/caperoma/models/tasks/feature.rb +27 -0
  31. data/lib/caperoma/models/tasks/fix.rb +56 -0
  32. data/lib/caperoma/models/tasks/meeting.rb +40 -0
  33. data/lib/caperoma/models/tasks/modules/git.rb +65 -0
  34. data/lib/caperoma/models/tasks/task_with_commit.rb +40 -0
  35. data/lib/caperoma/models/tasks/task_with_separate_branch.rb +42 -0
  36. data/lib/caperoma/services/airbrake_email_processor.rb +47 -0
  37. data/lib/caperoma/services/pivotal_fetcher.rb +108 -0
  38. data/lib/caperoma/version.rb +9 -0
  39. data/spec/caperoma_spec.rb +3 -21
  40. data/spec/factories/accounts.rb +10 -0
  41. data/spec/factories/branches.rb +9 -0
  42. data/spec/factories/projects.rb +8 -0
  43. data/spec/factories/report_recipients.rb +7 -0
  44. data/spec/factories/reports.rb +16 -0
  45. data/spec/factories/tasks.rb +37 -0
  46. data/spec/features/bug_spec.rb +60 -0
  47. data/spec/features/chore_spec.rb +60 -0
  48. data/spec/features/command_unknown_spec.rb +14 -0
  49. data/spec/features/config_spec.rb +161 -0
  50. data/spec/features/feature_spec.rb +60 -0
  51. data/spec/features/finish_spec.rb +18 -0
  52. data/spec/features/fix_spec.rb +60 -0
  53. data/spec/features/meeting_spec.rb +22 -0
  54. data/spec/features/projects_spec.rb +17 -0
  55. data/spec/features/report_recipientss_spec.rb +117 -0
  56. data/spec/features/reports_spec.rb +65 -0
  57. data/spec/features/status_spec.rb +33 -0
  58. data/spec/features/version_spec.rb +11 -0
  59. data/spec/models/account_spec.rb +51 -0
  60. data/spec/models/branch_spec.rb +8 -0
  61. data/spec/models/bug_spec.rb +33 -0
  62. data/spec/models/chore_spec.rb +33 -0
  63. data/spec/models/daily_report_spec.rb +38 -0
  64. data/spec/models/feature_spec.rb +33 -0
  65. data/spec/models/fix_spec.rb +55 -0
  66. data/spec/models/meeting_spec.rb +33 -0
  67. data/spec/models/project_spec.rb +11 -0
  68. data/spec/models/report_recipient_spec.rb +22 -0
  69. data/spec/models/report_spec.rb +16 -0
  70. data/spec/models/retrospective_report_spec.rb +38 -0
  71. data/spec/models/task_spec.rb +613 -0
  72. data/spec/models/task_with_commit_spec.rb +105 -0
  73. data/spec/models/task_with_separate_branch_spec.rb +97 -0
  74. data/spec/models/three_day_report_spec.rb +49 -0
  75. data/spec/spec_helper.rb +26 -16
  76. data/spec/support/capefile_generator.rb +36 -0
  77. data/spec/support/database_cleaner.rb +21 -0
  78. data/spec/support/stubs.rb +178 -9
  79. metadata +283 -42
  80. data/.document +0 -5
  81. data/README.rdoc +0 -26
  82. data/lib/caperoma/credentials.rb +0 -13
  83. data/lib/caperoma/jira_client.rb +0 -57
  84. data/spec/caperoma/credentials_spec.rb +0 -25
  85. data/spec/caperoma/jira_spec.rb +0 -35
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
4
+
5
+ RSpec.describe Chore, type: :model do
6
+ describe 'inheritence' do
7
+ it { expect(subject).to be_a_kind_of Task }
8
+ end
9
+
10
+ describe 'private methods' do
11
+ describe '#issue_type' do
12
+ let!(:project) { create :project, chore_jira_task_id: '1234' }
13
+
14
+ let!(:task) { create :chore, project: project }
15
+
16
+ it { expect(task.send(:issue_type)).to eq '1234' }
17
+ end
18
+
19
+ describe '#story_type' do
20
+ let!(:task) { create :chore }
21
+
22
+ it { expect(task.send(:story_type)).to eq 'chore' }
23
+ end
24
+
25
+ describe '#this_is_a_type_a_user_wants_to_create' do
26
+ let!(:project) { create :project, create_chores_in_pivotal: true }
27
+
28
+ let!(:task) { build :chore, project: project }
29
+
30
+ it { expect(task.send(:this_is_a_type_a_user_wants_to_create?)).to be_truthy }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
4
+
5
+ RSpec.describe DailyReport, type: :model do
6
+ describe 'relations' do
7
+ it { expect(subject).to have_many :tasks }
8
+ end
9
+
10
+ describe 'callbacks' do
11
+ describe '::asskgn_unreported_tasks' do
12
+ let!(:daily_report1) { create :daily_report }
13
+ let!(:three_day_report1) { create :three_day_report }
14
+
15
+ let!(:task1) { create :task, daily_report: daily_report1, three_day_report: nil, finished_at: Time.now }
16
+ let!(:task2) { create :task, daily_report: daily_report1, three_day_report: three_day_report1, finished_at: Time.now }
17
+ let!(:task3) { create :task, daily_report: nil, three_day_report: nil, finished_at: Time.now }
18
+ let!(:task4) { create :task, daily_report: nil, three_day_report: nil, finished_at: nil }
19
+
20
+ specify do
21
+ new_report = create :daily_report
22
+ expect(new_report.tasks).to match_array [task3]
23
+ end
24
+ end
25
+ end
26
+
27
+ describe 'message format' do
28
+ describe 'subject' do
29
+ let(:report) { create :daily_report }
30
+
31
+ specify do
32
+ Timecop.freeze(Time.parse('06/02/2015 15:06')) do
33
+ expect(report.send(:report_subject)).to eq 'Daily Report (Feb 6)'
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
4
+
5
+ RSpec.describe Feature, type: :model do
6
+ describe 'inheritence' do
7
+ it { expect(subject).to be_a_kind_of TaskWithSeparateBranch }
8
+ end
9
+
10
+ describe 'private methods' do
11
+ describe '#issue_type' do
12
+ let!(:project) { create :project, feature_jira_task_id: '1234' }
13
+
14
+ let!(:task) { create :feature, project: project }
15
+
16
+ it { expect(task.send(:issue_type)).to eq '1234' }
17
+ end
18
+
19
+ describe '#story_type' do
20
+ let!(:task) { create :feature }
21
+
22
+ it { expect(task.send(:story_type)).to eq 'feature' }
23
+ end
24
+
25
+ describe '#this_is_a_type_a_user_wants_to_create' do
26
+ let!(:project) { create :project, create_features_in_pivotal: true }
27
+
28
+ let!(:task) { build :feature, project: project }
29
+
30
+ it { expect(task.send(:this_is_a_type_a_user_wants_to_create?)).to be_truthy }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
4
+
5
+ RSpec.describe Fix, type: :model do
6
+ describe 'inheritence' do
7
+ it { expect(subject).to be_a_kind_of TaskWithCommit }
8
+ end
9
+
10
+ describe 'methods' do
11
+ describe 'description' do
12
+ let!(:task) { create :fix, description: 'blah' }
13
+
14
+ it 'should append last commit name' do
15
+ allow(task).to receive(:git_last_commit_name).and_return('some great commit')
16
+ expect(task.description).to eq "blah\n(For: some great commit)"
17
+ end
18
+ end
19
+ end
20
+
21
+ describe 'observers' do
22
+ describe '::update_parent_branch' do
23
+ let!(:task) { build :task_with_separate_branch }
24
+
25
+ it 'should get latest version of remote branch before switching' do
26
+ expect(task).to receive(:git_rebase_to_upstream)
27
+ task.save!
28
+ end
29
+ end
30
+ end
31
+
32
+ describe 'private methods' do
33
+ describe '#issue_type' do
34
+ let!(:project) { create :project, fix_jira_task_id: '1234' }
35
+
36
+ let!(:task) { create :fix, project: project }
37
+
38
+ it { expect(task.send(:issue_type)).to eq '1234' }
39
+ end
40
+
41
+ describe '#story_type' do
42
+ let!(:task) { create :fix }
43
+
44
+ it { expect(task.send(:story_type)).to eq 'chore' }
45
+ end
46
+
47
+ describe '#this_is_a_type_a_user_wants_to_create' do
48
+ let!(:project) { create :project, create_fixes_in_pivotal_as_chores: true }
49
+
50
+ let!(:task) { build :fix, project: project }
51
+
52
+ it { expect(task.send(:this_is_a_type_a_user_wants_to_create?)).to be_truthy }
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
4
+
5
+ RSpec.describe Meeting, type: :model do
6
+ describe 'inheritence' do
7
+ it { expect(subject).to be_a_kind_of Task }
8
+ end
9
+
10
+ describe 'private methods' do
11
+ describe '#issue_type' do
12
+ let!(:project) { create :project, meeting_jira_task_id: '1234' }
13
+
14
+ let!(:task) { create :meeting, project: project }
15
+
16
+ it { expect(task.send(:issue_type)).to eq '1234' }
17
+ end
18
+
19
+ describe '#story_type' do
20
+ let!(:task) { create :meeting }
21
+
22
+ it { expect(task.send(:story_type)).to eq 'chore' }
23
+ end
24
+
25
+ describe '#this_is_a_type_a_user_wants_to_create' do
26
+ let!(:project) { create :project, create_meetings_in_pivotal_as_chores: true }
27
+
28
+ let!(:task) { build :meeting, project: project }
29
+
30
+ it { expect(task.send(:this_is_a_type_a_user_wants_to_create?)).to be_truthy }
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
4
+
5
+ RSpec.describe Project, type: :model do
6
+ it { expect(subject).to have_many :branches }
7
+ it { expect(subject).to have_many :chores }
8
+ it { expect(subject).to have_many :bugs }
9
+ it { expect(subject).to have_many :features }
10
+ it { expect(subject).to have_many :meetings }
11
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
4
+
5
+ RSpec.describe ReportRecipient, type: :model do
6
+ describe 'validations' do
7
+ specify do
8
+ ['me@gmail.com', 'dude.due@gmail.com'].each do |value|
9
+ expect(subject).to allow_value(value).for(:email)
10
+ end
11
+ end
12
+
13
+ specify do
14
+ ['12345', '', nil].each do |value|
15
+ expect(subject).not_to allow_value(value).for(:email)
16
+ end
17
+ end
18
+
19
+ it { expect(subject).to validate_uniqueness_of(:email) }
20
+ it { expect(subject).to validate_presence_of(:email) }
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
4
+
5
+ RSpec.describe Report, type: :model do
6
+ describe '#to_addresses' do
7
+ let!(:recipient1) { create :report_recipient, email: 'dude1@example.com' }
8
+ let!(:recipient2) { create :report_recipient, email: 'dude2@example.com' }
9
+
10
+ let!(:report) { build :report }
11
+
12
+ specify do
13
+ expect(report.send(:to_addresses)).to match_array ['dude1@example.com', 'dude2@example.com']
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
4
+
5
+ RSpec.describe RetrospectiveReport, type: :model do
6
+ describe 'relations' do
7
+ it { expect(subject).to have_many :tasks }
8
+ end
9
+
10
+ describe 'callbacks' do
11
+ describe '::asskgn_unreported_tasks' do
12
+ let!(:daily_report1) { create :daily_report }
13
+ let!(:three_day_report1) { create :three_day_report }
14
+
15
+ let!(:task1) { create :task, daily_report: daily_report1, three_day_report: nil, retrospective_report: nil, finished_at: Time.now }
16
+ let!(:task2) { create :task, daily_report: daily_report1, three_day_report: three_day_report1, retrospective_report: nil, finished_at: Time.now }
17
+ let!(:task3) { create :task, daily_report: nil, three_day_report: nil, retrospective_report: nil, finished_at: Time.now }
18
+ let!(:task4) { create :task, daily_report: nil, three_day_report: nil, retrospective_report: nil, finished_at: nil }
19
+
20
+ specify do
21
+ new_report = create :retrospective_report
22
+ expect(new_report.tasks).to match_array [task1, task2, task3]
23
+ end
24
+ end
25
+ end
26
+
27
+ describe 'message format' do
28
+ describe 'subject' do
29
+ let(:report) { create :retrospective_report }
30
+
31
+ specify do
32
+ Timecop.freeze(Time.parse('06/02/2015 15:06')) do
33
+ expect(report.send(:report_subject)).to eq 'Weekly Report (Feb 2 - Feb 6)'
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,613 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
4
+
5
+ RSpec.describe Task, type: :model do
6
+ describe 'relations' do
7
+ it { expect(subject).to belong_to :project }
8
+ it { expect(subject).to belong_to :daily_report }
9
+ it { expect(subject).to belong_to :three_day_report }
10
+ it { expect(subject).to belong_to :retrospective_report }
11
+ end
12
+
13
+ describe 'validations' do
14
+ it { expect(subject).to validate_presence_of(:title) }
15
+
16
+ describe 'length' do
17
+ it { expect(subject).to allow_value(nil).for(:pivotal_id) }
18
+ it { expect(subject).to allow_value('123456').for(:pivotal_id) }
19
+ it { expect(subject).to allow_value('1234567').for(:pivotal_id) }
20
+ it { expect(subject).to allow_value('12345678').for(:pivotal_id) }
21
+ it { expect(subject).to allow_value('123456789').for(:pivotal_id) }
22
+ it { expect(subject).not_to allow_value('#12345678').for(:pivotal_id) }
23
+ it { expect(subject).not_to allow_value('12').for(:pivotal_id) }
24
+ it { expect(subject).not_to allow_value('123.45678').for(:pivotal_id) }
25
+ end
26
+ end
27
+
28
+ describe 'scopes' do
29
+ describe '::unfinished' do
30
+ let!(:started) { create :task, finished_at: nil }
31
+ let!(:finished) { create :task, finished_at: Time.now }
32
+
33
+ it 'should return tasks without finished_at time' do
34
+ expect(Task.unfinished).to eq [started]
35
+ end
36
+ end
37
+
38
+ describe '::finished' do
39
+ let!(:started) { create :task, finished_at: nil }
40
+ let!(:finished) { create :task, finished_at: Time.now }
41
+
42
+ it 'should return tasks without finished_at time' do
43
+ expect(Task.finished).to eq [finished]
44
+ end
45
+ end
46
+ end
47
+
48
+ describe 'class_methods' do
49
+ describe '::finish_started' do
50
+ let!(:started) { create :task, finished_at: nil }
51
+
52
+ it 'should finish started tasks' do
53
+ Task.finish_started(nil)
54
+
55
+ expect(started.reload.finished_at).to be_present
56
+ end
57
+ end
58
+
59
+ describe '::pause_started' do
60
+ let!(:started) { create :task, finished_at: nil }
61
+
62
+ it 'should finish started tasks' do
63
+ Task.pause_started(nil)
64
+
65
+ expect(started.reload.finished_at).to be_present
66
+ end
67
+ end
68
+
69
+ describe '::abort_started' do
70
+ let!(:started) { create :task, finished_at: nil }
71
+
72
+ it 'should abort started tasks' do
73
+ Task.abort_started(nil)
74
+
75
+ expect(started.reload.finished_at).to be_present
76
+ end
77
+ end
78
+
79
+ describe '::abort_started_without_time' do
80
+ let!(:started) { create :task, finished_at: nil }
81
+
82
+ it 'should abort started tasks without time' do
83
+ Task.abort_started_without_time(nil)
84
+
85
+ expect(started.reload.finished_at).to be_present
86
+ end
87
+ end
88
+ end
89
+
90
+ describe 'methods' do
91
+ context 'pivotal_id present' do
92
+ let!(:task) { create :task, finished_at: nil, pivotal_id: '12345678' }
93
+ describe '#finish' do
94
+ it 'should finish it and log time' do
95
+ expect(task).to receive :close_issue_on_jira
96
+ expect(task).to receive :log_work_to_jira
97
+ expect(task).to receive :finish_on_pivotal
98
+ task.finish(nil)
99
+ expect(task.finished_at).to be_present
100
+ end
101
+ end
102
+
103
+ describe '#pause' do
104
+ it 'should pause it and log time' do
105
+ expect(task).to receive :close_issue_on_jira
106
+ expect(task).to receive :log_work_to_jira
107
+ expect(task).to receive :finish_on_pivotal
108
+ task.pause(nil)
109
+ expect(task.finished_at).to be_present
110
+ end
111
+ end
112
+
113
+ describe '#abort' do
114
+ it 'should abort it and log time' do
115
+ expect(task).to receive :close_issue_on_jira
116
+ expect(task).to receive :log_work_to_jira
117
+ expect(task).to receive :finish_on_pivotal
118
+ task.abort(nil)
119
+ expect(task.finished_at).to be_present
120
+ end
121
+ end
122
+
123
+ describe '#abort_without_time' do
124
+ it 'should abort it and not log time' do
125
+ expect(task).to receive :close_issue_on_jira
126
+ expect(task).not_to receive :log_work_to_jira
127
+ expect(task).not_to receive :finish_on_pivotal
128
+ task.abort_without_time(nil)
129
+ expect(task.finished_at).to be_present
130
+ end
131
+ end
132
+ end
133
+
134
+ context 'pivotal_id blank' do
135
+ let!(:task) { create :task, finished_at: nil, pivotal_id: nil }
136
+ describe '#finish' do
137
+ it 'should finish it and log time' do
138
+ expect(task).to receive :close_issue_on_jira
139
+ expect(task).to receive :log_work_to_jira
140
+ expect(task).not_to receive :finish_on_pivotal
141
+ task.finish(nil)
142
+ expect(task.finished_at).to be_present
143
+ end
144
+ end
145
+
146
+ describe '#pause' do
147
+ it 'should pause it and log time' do
148
+ expect(task).to receive :close_issue_on_jira
149
+ expect(task).to receive :log_work_to_jira
150
+ expect(task).not_to receive :finish_on_pivotal
151
+ task.pause(nil)
152
+ expect(task.finished_at).to be_present
153
+ end
154
+ end
155
+
156
+ describe '#abort' do
157
+ it 'should abort it and log time' do
158
+ expect(task).to receive :close_issue_on_jira
159
+ expect(task).to receive :log_work_to_jira
160
+ expect(task).not_to receive :finish_on_pivotal
161
+ task.abort(nil)
162
+ expect(task.finished_at).to be_present
163
+ end
164
+ end
165
+
166
+ describe '#abort_without_time' do
167
+ it 'should abort it and not log time' do
168
+ expect(task).to receive :close_issue_on_jira
169
+ expect(task).not_to receive :log_work_to_jira
170
+ expect(task).not_to receive :finish_on_pivotal
171
+ task.abort_without_time(nil)
172
+ expect(task.finished_at).to be_present
173
+ end
174
+ end
175
+ end
176
+
177
+ # TODO: handle cases where jira/pt ids are present, but neither jira nor pt are set up.
178
+ end
179
+
180
+ describe 'observers' do
181
+ let!(:project) { create :project, jira_project_id: 135 }
182
+ before { expect(SecureRandom).to receive(:uuid).and_return '123' }
183
+
184
+ describe '::generate_uuid' do
185
+ let(:task) { build :task }
186
+
187
+ it 'should_generate_random_string' do
188
+ task.save
189
+ expect(task.uuid).to eq '123'
190
+ end
191
+ end
192
+
193
+ describe '::set_start_time' do
194
+ let!(:timestamp) { Time.parse('5 April 2014') }
195
+ before { expect(Time).to receive(:now).and_return timestamp }
196
+
197
+ context 'no additional time' do
198
+ let(:task) { build :task }
199
+ it 'should set setarted_at time' do
200
+ task.save
201
+ expect(task.reload.started_at).to eq timestamp
202
+ end
203
+ end
204
+
205
+ context 'additional time present' do
206
+ let(:task) { build :task, additional_time: '23' }
207
+ it 'should move started_at back to past by X minutes' do
208
+ task.save
209
+ expect(task.reload.started_at).to eq (timestamp - 23.minutes)
210
+ end
211
+ end
212
+ end
213
+
214
+ describe '::create_issue_on_jira', :unstub_jira_creation do
215
+ context 'jira account present' do
216
+ let(:task) { create :task }
217
+ let!(:account) { create :account, type: '--jira' }
218
+ let(:faraday) { double('Faraday', post: response) }
219
+ let(:response) { double('Faraday', body: JIRA_ISSUE_CREATION_RESPONSE) }
220
+
221
+ it 'should create task in Jira after create' do
222
+ expect(Faraday).to receive(:new).and_return faraday
223
+
224
+ task.save
225
+
226
+ task.reload.tap do |task|
227
+ expect(task.jira_id).to eq '10000'
228
+ expect(task.jira_key).to eq 'TST-24'
229
+ expect(task.jira_url).to eq 'http://www.example.com/jira/rest/api/2/issue/10000'
230
+ end
231
+ end
232
+ end
233
+
234
+ context 'jira account not present' do
235
+ let(:task) { create :task }
236
+ let(:faraday) { double('Faraday', post: response) }
237
+ let(:response) { double('Faraday', body: JIRA_ISSUE_CREATION_RESPONSE) }
238
+
239
+ it 'should not create task in Jira after create' do
240
+ allow(Faraday).to receive(:new).and_return faraday
241
+ expect(task).not_to receive :create_issue_on_jira
242
+
243
+ task.save
244
+ end
245
+ end
246
+ end
247
+
248
+ describe '::start_issue_on_jira' do
249
+ let(:task) { build :task, jira_key: jira_key }
250
+
251
+ context 'account present, jira id present' do
252
+ let!(:account) { create :account, type: '--jira' }
253
+ let!(:jira_key) { 'OK-1' }
254
+
255
+ it 'should start task in Jira after create' do
256
+ expect(task).to receive(:start_issue_on_jira)
257
+
258
+ task.save
259
+ end
260
+ end
261
+
262
+ context 'account not present, jira id not present' do
263
+ let!(:jira_key) { 'OK-1' }
264
+
265
+ it 'should start task in Jira after create' do
266
+ expect(task).not_to receive(:start_issue_on_jira)
267
+
268
+ task.save
269
+ end
270
+ end
271
+
272
+ context 'account present, jira id present' do
273
+ let!(:account) { create :account, type: '--jira' }
274
+ let!(:jira_key) { nil }
275
+
276
+ it 'should start task in Jira after create' do
277
+ expect(task).not_to receive(:start_issue_on_jira)
278
+
279
+ task.save
280
+ end
281
+ end
282
+
283
+ context 'account not present, jira id not present' do
284
+ let!(:jira_key) { nil }
285
+
286
+ it 'should start task in Jira after create' do
287
+ expect(task).not_to receive(:start_issue_on_jira)
288
+
289
+ task.save
290
+ end
291
+ end
292
+ end
293
+
294
+ describe '::create_issue_on_pivotal', :unstub_pivotal_creation do
295
+ context 'pivotal account present' do
296
+ let(:task) { build :task, pivotal_id: pt_id }
297
+ let!(:account) { create :account, type: '--pivotal' }
298
+ let(:faraday) { double('Faraday', post: response) }
299
+ let(:response) { double('Faraday', body: PIVOTAL_ISSUE_CREATION_RESPONSE) }
300
+
301
+ before { allow(task).to receive(:this_is_a_type_a_user_wants_to_create?).and_return(should_create) }
302
+
303
+ context 'PT id present but should not create' do
304
+ let(:pt_id) { '567890123' }
305
+ let(:should_create) { false }
306
+
307
+ it 'should not create task in Pivotal' do
308
+ task.save
309
+
310
+ task.reload.tap do |task|
311
+ expect(task.pivotal_id).to eq '567890123'
312
+ end
313
+ end
314
+ end
315
+
316
+ context 'PT id present but should create' do
317
+ let(:pt_id) { '567890123' }
318
+ let(:should_create) { true }
319
+
320
+ it 'should not create task in Pivotal' do
321
+ task.save
322
+
323
+ task.reload.tap do |task|
324
+ expect(task.pivotal_id).to eq '567890123'
325
+ end
326
+ end
327
+ end
328
+
329
+ context 'PT id blank but should not create' do
330
+ let(:pt_id) { nil }
331
+ let(:should_create) { false }
332
+
333
+ it 'should not create task in Pivotal' do
334
+ task.save
335
+
336
+ task.reload.tap do |task|
337
+ expect(task.pivotal_id).to eq nil
338
+ end
339
+ end
340
+ end
341
+
342
+ context 'PT id blank and should create' do
343
+ let(:pt_id) { nil }
344
+ let(:should_create) { true }
345
+
346
+ it 'should create task in Pivotal' do
347
+ expect(Faraday).to receive(:new).and_return faraday
348
+ task.save
349
+
350
+ task.reload.tap do |task|
351
+ expect(task.pivotal_id).to eq '12345678'
352
+ end
353
+ end
354
+ end
355
+ end
356
+
357
+ context 'pivotal account blank' do
358
+ let(:task) { build :task, pivotal_id: pt_id }
359
+ let(:faraday) { double('Faraday', post: response) }
360
+ let(:response) { double('Faraday', body: PIVOTAL_ISSUE_CREATION_RESPONSE) }
361
+
362
+ before { allow(task).to receive(:this_is_a_type_a_user_wants_to_create?).and_return(should_create) }
363
+
364
+ context 'PT id present but should not create' do
365
+ let(:pt_id) { '567890123' }
366
+ let(:should_create) { false }
367
+
368
+ it 'should not create task in Pivotal' do
369
+ task.save
370
+
371
+ task.reload.tap do |task|
372
+ expect(task.pivotal_id).to eq '567890123'
373
+ end
374
+ end
375
+ end
376
+
377
+ context 'PT id present but should create' do
378
+ let(:pt_id) { '567890123' }
379
+ let(:should_create) { true }
380
+
381
+ it 'should not create task in Pivotal' do
382
+ task.save
383
+
384
+ task.reload.tap do |task|
385
+ expect(task.pivotal_id).to eq '567890123'
386
+ end
387
+ end
388
+ end
389
+
390
+ context 'PT id blank but should not create' do
391
+ let(:pt_id) { nil }
392
+ let(:should_create) { false }
393
+
394
+ it 'should not create task in Pivotal' do
395
+ task.save
396
+
397
+ task.reload.tap do |task|
398
+ expect(task.pivotal_id).to eq nil
399
+ end
400
+ end
401
+ end
402
+
403
+ context 'PT id blank and should create' do
404
+ let(:pt_id) { nil }
405
+ let(:should_create) { true }
406
+
407
+ it 'should create task in Pivotal' do
408
+ allow(Faraday).to receive(:new).and_return faraday
409
+ task.save
410
+
411
+ task.reload.tap do |task|
412
+ expect(task.pivotal_id).to be_blank
413
+ end
414
+ end
415
+ end
416
+ end
417
+ end
418
+
419
+ describe '::start_issue_on_pivotal' do
420
+ let(:task) { build :task, pivotal_id: pivotal_id }
421
+ # before { allow(task).to receive(:this_is_a_type_a_user_wants_to_create?).and_return should_create_this_type }
422
+
423
+ context 'pt id present, pt account present' do
424
+ let(:pivotal_id) { '12345678' }
425
+ let!(:account) { create :account, type: '--pivotal' }
426
+
427
+ it 'should start task in pivotal after create' do
428
+ expect(task).to receive(:start_issue_on_pivotal)
429
+
430
+ task.save
431
+ end
432
+ end
433
+
434
+ context 'pt id blank, pt account present' do
435
+ let(:pivotal_id) { nil }
436
+ let!(:account) { create :account, type: '--pivotal' }
437
+
438
+ it 'should not start task in pivotal after create' do
439
+ expect(task).not_to receive(:start_issue_on_pivotal)
440
+
441
+ task.save
442
+ end
443
+ end
444
+
445
+ context 'pt id present, pt account blank' do
446
+ let(:pivotal_id) { '12345678' }
447
+
448
+ it 'should start task in pivotal after create' do
449
+ expect(task).not_to receive(:start_issue_on_pivotal)
450
+
451
+ task.save
452
+ end
453
+ end
454
+
455
+ context 'pt id blank, pt account blank' do
456
+ let(:pivotal_id) { nil }
457
+
458
+ it 'should not start task in pivotal after create' do
459
+ expect(task).not_to receive(:start_issue_on_pivotal)
460
+
461
+ task.save
462
+ end
463
+ end
464
+ end
465
+
466
+ describe '::output_jira_key', :unstub_key_output, :unstub_puts do
467
+ let(:task) { build :task, jira_key: jira_key }
468
+
469
+ context 'jira_key present' do
470
+ let(:jira_key) { 'TST-24' }
471
+
472
+ it 'should output ID to STDOUT' do
473
+ expect(STDOUT).to receive(:puts).with('TST-24')
474
+ task.save
475
+ end
476
+ end
477
+
478
+ context 'jira_key present' do
479
+ let(:jira_key) { nil }
480
+
481
+ it 'should not output ID to STDOUT' do
482
+ expect(STDOUT).not_to receive(:puts).with('TST-24')
483
+ task.save
484
+ end
485
+ end
486
+ end
487
+ end
488
+
489
+ describe 'private methods' do
490
+ let!(:project) { create :project, jira_project_id: '123' }
491
+ let!(:account) { create :account, type: '--jira', username: 'someuser' }
492
+
493
+ describe '#create_issue_on_jira_data' do
494
+ let!(:task) { create :task, title: 'dupis', description: 'bamis', project: project }
495
+
496
+ it 'should format hash' do
497
+ allow(task).to receive(:issue_type).and_return '492'
498
+ result = task.send(:create_issue_on_jira_data)
499
+ JSON.parse(result).tap do |format|
500
+ expect(format['fields']['project']['id']).to eq '123'
501
+ expect(format['fields']['issuetype']['id']).to eq '492'
502
+ expect(format['fields']['summary']).to eq 'dupis'
503
+ expect(format['fields']['assignee']['name']).to eq 'someuser'
504
+ end
505
+ end
506
+ end
507
+
508
+ describe '#start_issue_on_jira_data' do
509
+ let!(:project) { create :project, jira_transition_id_in_progress: '12345' }
510
+
511
+ let!(:task) { create :task, project: project }
512
+
513
+ it 'should format hash' do
514
+ result = task.send(:start_issue_on_jira_data)
515
+ JSON.parse(result).tap do |format|
516
+ expect(format['transition']['id']).to eq '12345'
517
+ end
518
+ end
519
+ end
520
+
521
+ describe '#close_issue_on_jira_data' do
522
+ let!(:project) { create :project, jira_transition_id_done: '12345' }
523
+
524
+ let!(:task) { create :task, project: project }
525
+
526
+ it 'should format hash' do
527
+ result = task.send(:close_issue_on_jira_data)
528
+ JSON.parse(result).tap do |format|
529
+ expect(format['transition']['id']).to eq '12345'
530
+ end
531
+ end
532
+ end
533
+
534
+ describe '#log_work_to_jira_data' do
535
+ let!(:task) { create :task }
536
+
537
+ it 'should format hash' do
538
+ allow(task).to receive(:current_time).and_return 'time'
539
+ allow(task).to receive(:time_spent).and_return 'spent'
540
+ result = task.send(:log_work_to_jira_data, 'some comment')
541
+
542
+ JSON.parse(result).tap do |format|
543
+ expect(format['comment']).to eq 'some comment'
544
+ expect(format['started']).to eq 'time'
545
+ expect(format['timeSpent']).to eq 'spent'
546
+ end
547
+ end
548
+ end
549
+
550
+ describe '#create_issue_on_pivotal_data' do
551
+ let!(:task) { create :task, title: 'dupis', description: 'bamis', project: project }
552
+
553
+ it 'should format hash' do
554
+ allow(task).to receive(:story_type).and_return 'chore'
555
+ result = task.send(:create_issue_on_pivotal_data)
556
+ JSON.parse(result).tap do |format|
557
+ expect(format['current_state']).to eq 'unstarted'
558
+ expect(format['estimate']).to eq 1
559
+ expect(format['name']).to eq 'dupis'
560
+ expect(format['story_type']).to eq 'chore'
561
+ end
562
+ end
563
+ end
564
+
565
+ describe '#finish_on_pivotal_data' do
566
+ let!(:task) { create :task }
567
+
568
+ it 'should format hash' do
569
+ allow(task).to receive(:story_type).and_return 'chore'
570
+ result = task.send(:finish_on_pivotal_data)
571
+ JSON.parse(result).tap do |format|
572
+ expect(format['current_state']).to eq 'finished'
573
+ end
574
+ end
575
+ end
576
+
577
+ describe '#start_issue_on_pivotal_data' do
578
+ let!(:task) { create :task }
579
+
580
+ it 'should format hash' do
581
+ allow(task).to receive(:story_type).and_return 'chore'
582
+ result = task.send(:start_issue_on_pivotal_data)
583
+ JSON.parse(result).tap do |format|
584
+ expect(format['current_state']).to eq 'started'
585
+ end
586
+ end
587
+ end
588
+
589
+ describe '#current_time' do
590
+ let!(:task) { create :task, project: project }
591
+ let!(:time) { Time.parse('5 April 2014') }
592
+
593
+ it 'should format time' do
594
+ allow(Time).to receive_message_chain(:now, :in_time_zone).and_return time
595
+ result = task.send(:current_time)
596
+ expect(result).to eq '2014-04-05T00:00:00.000+0000'
597
+ end
598
+ end
599
+
600
+ describe '#time_spent' do
601
+ let!(:task) { create :task, project: project }
602
+ let!(:start_time) { Time.parse('5 April 2014 1:30PM') }
603
+ let!(:finish_time) { Time.parse('5 April 2014 2:45PM') }
604
+
605
+ it 'should return formatted time difference' do
606
+ expect(task).to receive(:started_at).and_return start_time
607
+ expect(task).to receive(:finished_at).and_return finish_time
608
+ result = task.send(:time_spent)
609
+ expect(result).to eq '1h 15m'
610
+ end
611
+ end
612
+ end
613
+ end