caperoma 0.1.0 → 4.0.1

Sign up to get free protection for your applications and to get access to all the features.
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