trello_effort_tracker 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. data/.gitignore +25 -0
  2. data/.rspec +3 -0
  3. data/.rvmrc.template +2 -0
  4. data/.travis.yml +21 -0
  5. data/Gemfile +22 -0
  6. data/Gemfile.lock +101 -0
  7. data/LICENSE.txt +15 -0
  8. data/README.md +159 -0
  9. data/Rakefile +72 -0
  10. data/config/config.template.yml +7 -0
  11. data/config/mongoid.template.yml +24 -0
  12. data/lib/patches/trello/member.rb +20 -0
  13. data/lib/startup_trello.rb +2 -0
  14. data/lib/trello_effort_tracker/effort.rb +27 -0
  15. data/lib/trello_effort_tracker/estimate.rb +25 -0
  16. data/lib/trello_effort_tracker/google_docs_exporter.rb +67 -0
  17. data/lib/trello_effort_tracker/member.rb +46 -0
  18. data/lib/trello_effort_tracker/mongoid_helper.rb +13 -0
  19. data/lib/trello_effort_tracker/tracked_card.rb +103 -0
  20. data/lib/trello_effort_tracker/tracking.rb +130 -0
  21. data/lib/trello_effort_tracker/trello_authorize.rb +32 -0
  22. data/lib/trello_effort_tracker/trello_configuration.rb +33 -0
  23. data/lib/trello_effort_tracker/trello_tracker.rb +48 -0
  24. data/lib/trello_effort_tracker/version.rb +3 -0
  25. data/lib/trello_effort_tracker.rb +23 -0
  26. data/script/ci/before_script.sh +1 -0
  27. data/script/ci/run_build.sh +2 -0
  28. data/script/crontab.template +8 -0
  29. data/script/mate.sh +1 -0
  30. data/spec/effort_spec.rb +52 -0
  31. data/spec/estimate_spec.rb +38 -0
  32. data/spec/integration/trello_authorization_spec.rb +12 -0
  33. data/spec/member_spec.rb +45 -0
  34. data/spec/spec_helper.rb +21 -0
  35. data/spec/tracked_card_spec.rb +267 -0
  36. data/spec/tracking_spec.rb +236 -0
  37. data/spec/trello_authorize_spec.rb +71 -0
  38. data/spec/trello_configuration_spec.rb +43 -0
  39. data/trello_effort_tracker.gemspec +19 -0
  40. metadata +86 -0
@@ -0,0 +1,267 @@
1
+ require 'spec_helper'
2
+
3
+ describe TrackedCard do
4
+
5
+ before(:each) do
6
+ Date.stub(:today).and_return(Date.parse("2012-11-05"))
7
+ TrackedCard.delete_all
8
+ end
9
+
10
+ after(:each) do
11
+ TrackedCard.delete_all
12
+ end
13
+
14
+ subject(:card) { TrackedCard.new(name: "any", short_id: 1234, trello_id: "123123") }
15
+
16
+ %w{piero tommaso michele}.each do |username|
17
+ let(username.to_sym) { Member.new(username: username) }
18
+ end
19
+
20
+ describe "validations" do
21
+ it "is not valid when a name is not given" do
22
+ TrackedCard.new(trello_id: "123456789", short_id: 1234).should_not be_valid
23
+ end
24
+
25
+ it "is not valid when a short_id is not given" do
26
+ TrackedCard.new(name: "any", trello_id: "123456789").should_not be_valid
27
+ end
28
+
29
+ it "is not valid when a trello_id is not given" do
30
+ TrackedCard.new(name: "any", short_id: 1234).should_not be_valid
31
+ end
32
+
33
+ it "is valid when has a name, a short id and a trello id" do
34
+ TrackedCard.new(name: "any", trello_id: "123456789", short_id: 1234).should be_valid
35
+ end
36
+ end
37
+
38
+ describe ".find_by_trello_id" do
39
+ it "find a card given its Trello id" do
40
+ card = TrackedCard.create(name: "any card", short_id: 1234, trello_id: "1")
41
+ another_card = TrackedCard.create(name: "another card", short_id: 3456, trello_id: "2")
42
+
43
+ TrackedCard.find_by_trello_id("1").should == card
44
+ TrackedCard.find_by_trello_id("3").should == nil
45
+ end
46
+ end
47
+
48
+ describe ".update_or_create_with" do
49
+ let(:trello_card) { Trello::Card.new("id" => "ABC123", "name" => "a name", "idShort" => 1, "desc" => "any description") }
50
+
51
+ it "creates a tracked card on a given trello card" do
52
+ tracked_card = TrackedCard.update_or_create_with(trello_card)
53
+
54
+ tracked_card.name.should == "a name"
55
+ tracked_card.trello_id == "ABC123"
56
+ tracked_card.short_id == 1
57
+ end
58
+
59
+ it "updates an existing tracked card on a given trello card" do
60
+ existing_card = TrackedCard.create(name: "an old name", short_id: 1234, trello_id: trello_card.id)
61
+
62
+ updated_card = TrackedCard.update_or_create_with(trello_card)
63
+
64
+ updated_card.should == existing_card
65
+ updated_card.name.should == "a name"
66
+ end
67
+
68
+ it "is nil when the trello card is not valid" do
69
+ invalid_trello_card = Trello::Card.new("id" => nil, "name" => nil)
70
+
71
+ TrackedCard.update_or_create_with(invalid_trello_card).should be_nil
72
+ TrackedCard.all.should be_empty
73
+ end
74
+
75
+ end
76
+
77
+ describe ".build_from" do
78
+ it "builds a TrackedCard from a Trello Card" do
79
+ tracked_card = TrackedCard.build_from(Trello::Card.new("name" => "a name", "desc" => "any description"))
80
+
81
+ tracked_card.name.should == "a name"
82
+ tracked_card.description.should == "any description"
83
+ end
84
+
85
+ it "takes the Trello Card id and set it as trello_id" do
86
+ tracked_card = TrackedCard.build_from(Trello::Card.new("id" => "abc123", "name" => "a name", "desc" => "any description"))
87
+
88
+ tracked_card.id.should_not == "abc123"
89
+ tracked_card.trello_id.should == "abc123"
90
+ end
91
+
92
+ end
93
+
94
+ it "has no estimates and efforts initially" do
95
+ card.estimates.should be_empty
96
+ card.efforts.should be_empty
97
+ end
98
+
99
+ it "is possible to add estimates" do
100
+ card.estimates << Estimate.new(amount: 5, date: Date.yesterday)
101
+ card.estimates << Estimate.new(amount: 12, date: Date.today)
102
+
103
+ card.estimates.should have(2).estimates
104
+ end
105
+
106
+ it "is possible to add efforts" do
107
+ card.efforts << Effort.new(amount: 3, date: Date.today, members: [piero, tommaso])
108
+ card.efforts << Effort.new(amount: 5, date: Date.today, members: [tommaso])
109
+
110
+ card.efforts.should have(2).efforts
111
+ end
112
+
113
+ describe "equality" do
114
+ it "is equal to another TrelloCard when the trello id is the same" do
115
+ card = TrackedCard.new(name: "a name", trello_id: "123456789")
116
+ same_card = TrackedCard.new(name: "a name", trello_id: "123456789")
117
+ another_card = TrackedCard.new(name: "a name", trello_id: "987654321")
118
+
119
+ card.should == same_card
120
+ card.should_not == another_card
121
+ end
122
+ end
123
+
124
+ describe "#total_effort" do
125
+ it "is zero when there's no effort" do
126
+ card.total_effort.should == 0
127
+ end
128
+
129
+ it "computes the total effort on the card" do
130
+ card.efforts << Effort.new(amount: 3, date: Date.today, members: [piero, tommaso])
131
+ card.efforts << Effort.new(amount: 5, date: Date.today, members: [tommaso])
132
+
133
+ card.total_effort.should == 3+5
134
+ end
135
+ end
136
+
137
+ describe "#last_estimate_error" do
138
+ it "is nil when the card has no estimate" do
139
+ card.efforts << Effort.new(amount: 5, date: Date.today, members: [tommaso])
140
+
141
+ card.last_estimate_error.should be_nil
142
+ end
143
+
144
+ it "is nil when the card has no effort" do
145
+ card.efforts << Estimate.new(amount: 5, date: Date.today)
146
+
147
+ card.last_estimate_error.should be_nil
148
+ end
149
+
150
+ it "is zero when actual effort is equal to estimate" do
151
+ card.estimates << Estimate.new(amount: 5, date: Date.today)
152
+ card.efforts << Effort.new(amount: 5, date: Date.today, members: [tommaso])
153
+
154
+ card.last_estimate_error.should == 0.0
155
+ end
156
+
157
+ it "is 100 when the actual effort is twice the given estimate" do
158
+ card.estimates << Estimate.new(amount: 5, date: Date.today)
159
+ card.efforts << Effort.new(amount: 10, date: Date.today, members: [tommaso])
160
+
161
+ card.last_estimate_error.should == 100.0
162
+ end
163
+
164
+ it "is -50 when the actual effort is half of the given estimate" do
165
+ card.estimates << Estimate.new(amount: 10, date: Date.today)
166
+ card.efforts << Effort.new(amount: 5, date: Date.today, members: [tommaso])
167
+
168
+ card.last_estimate_error.should == -50.0
169
+ end
170
+
171
+ it "is rounded with two decimal digits" do
172
+ card.estimates << Estimate.new(amount: 3, date: Date.today)
173
+ card.efforts << Effort.new(amount: 5, date: Date.today, members: [tommaso])
174
+
175
+ card.last_estimate_error.should == 66.67
176
+ end
177
+
178
+ describe "#estimate_errors" do
179
+
180
+ it "collects all the estimate errors against the actual effort" do
181
+ card.estimates << Estimate.new(amount: 5, date: Date.yesterday)
182
+ card.efforts << Effort.new(amount: 10, date: Date.yesterday, members: [tommaso])
183
+
184
+ card.estimates << Estimate.new(amount: 10, date: Date.today)
185
+ card.efforts << Effort.new(amount: 5, date: Date.today, members: [tommaso])
186
+
187
+ card.estimate_errors.should == [200.0, 50.0]
188
+ end
189
+ end
190
+
191
+ end
192
+
193
+ describe "#members" do
194
+ it "lists all the members which spent some effort on the card" do
195
+ card.efforts << Effort.new(amount: 3, date: Date.today, members: [piero, tommaso])
196
+ card.efforts << Effort.new(amount: 5, date: Date.today, members: [tommaso])
197
+ card.efforts << Effort.new(amount: 5, date: Date.today, members: [tommaso, michele])
198
+
199
+ card.members.should == [piero, tommaso, michele]
200
+ end
201
+ end
202
+
203
+ describe "#working_start_date" do
204
+
205
+ it "is the date of the first effort spent on the card" do
206
+ card.efforts << Effort.new(amount: 5, date: Date.today, members: [tommaso])
207
+ card.efforts << Effort.new(amount: 3, date: Date.yesterday, members: [tommaso])
208
+ card.efforts << Effort.new(amount: 5, date: Date.tomorrow, members: [tommaso])
209
+
210
+ card.working_start_date.should == Date.yesterday
211
+ end
212
+ end
213
+
214
+ describe "#first_activity_date" do
215
+ it "is the date of the first effort or estimate given on the card" do
216
+ card.estimates << Estimate.new(amount: 5, date: Date.yesterday)
217
+ card.estimates << Estimate.new(amount: 12, date: Date.yesterday.prev_day)
218
+ card.estimates << Estimate.new(amount: 12, date: Date.tomorrow)
219
+
220
+ card.efforts << Effort.new(amount: 3, date: Date.yesterday, members: [tommaso])
221
+ card.efforts << Effort.new(amount: 5, date: Date.today, members: [tommaso])
222
+
223
+ card.first_activity_date.should == Date.yesterday.prev_day
224
+ end
225
+ end
226
+
227
+ describe "#first_estimate_date" do
228
+ it "is the date of the first estimate given on the card" do
229
+ card.estimates << Estimate.new(amount: 5, date: Date.tomorrow)
230
+ card.estimates << Estimate.new(amount: 12, date: Date.yesterday.prev_day)
231
+ card.estimates << Estimate.new(amount: 12, date: Date.today)
232
+
233
+ card.first_estimate_date.should == Date.yesterday.prev_day
234
+ end
235
+ end
236
+
237
+ describe "#last_estimate_date" do
238
+ it "is the date of the last estimate given on the card" do
239
+ card.estimates << Estimate.new(amount: 5, date: Date.yesterday)
240
+ card.estimates << Estimate.new(amount: 12, date: Date.tomorrow)
241
+ card.estimates << Estimate.new(amount: 12, date: Date.today)
242
+
243
+ card.last_estimate_date.should == Date.tomorrow
244
+ end
245
+ end
246
+
247
+ describe "#no_tracking?" do
248
+ it "is false when there's no effort or estimate tracked on the card" do
249
+ card.no_tracking?.should be_true
250
+
251
+ card.estimates << Estimate.new(amount: 5, date: Date.yesterday)
252
+ card.no_tracking?.should be_false
253
+ end
254
+ end
255
+
256
+ describe "#to_s" do
257
+ it "describes the card as a string" do
258
+ card = TrackedCard.new(name: "A Story Name")
259
+ card.estimates << Estimate.new(amount: 5, date: Date.today)
260
+ card.efforts << Effort.new(amount: 3, date: Date.today, members: [Member.new(username: "piero"), Member.new(username: "tommaso")])
261
+ card.efforts << Effort.new(amount: 6, date: Date.today, members: [Member.new(username: "piero"), Member.new(username: "tommaso")])
262
+
263
+ card.to_s.should == %Q{[A Story Name]. Total effort: 9.0h. Estimates ["[2012-11-05] estimated 5.0 hours"]. Efforts: ["[2012-11-05] spent 3.0 hours by @piero, @tommaso", "[2012-11-05] spent 6.0 hours by @piero, @tommaso"]}
264
+ end
265
+ end
266
+
267
+ end
@@ -0,0 +1,236 @@
1
+ require 'spec_helper'
2
+
3
+ describe Tracking do
4
+
5
+ TIME_MEASUREMENTS = {
6
+ hours: 'h',
7
+ days: 'd',
8
+ giorni: 'g',
9
+ pomodori: 'p'
10
+ }
11
+
12
+ let(:unrecognized_notification) { create_notification(data: { 'text' => '@trackinguser hi there!' }) }
13
+
14
+ describe "#unknown_format?" do
15
+ it "tells when a notification cannot be interpreted as a tracking info" do
16
+ Tracking.new(unrecognized_notification).unknown_format?.should be_true
17
+
18
+ with_message("@trackinguser +30m") { |tracking| tracking.unknown_format?.should be_true }
19
+ end
20
+
21
+ end
22
+
23
+ describe "#estimate?" do
24
+ it "is false when the notification does not contain an estimate" do
25
+ Tracking.new(unrecognized_notification).estimate?.should be_false
26
+ end
27
+
28
+ TIME_MEASUREMENTS.each_key do |time_measurement|
29
+ it "is true when the notification contains an estimate in #{time_measurement}" do
30
+ tracking_estimate = Tracking.new(create_estimate(time_measurement))
31
+
32
+ tracking_estimate.estimate?.should be_true
33
+ tracking_estimate.effort?.should be_false
34
+ end
35
+ end
36
+
37
+ end
38
+
39
+ describe "#estimate" do
40
+
41
+ it "is nil when the notification does not contain an estimate" do
42
+ Tracking.new(unrecognized_notification).estimate.should be_nil
43
+ end
44
+
45
+ it "is the hour-based estimate when the notification contains an estimate in hours" do
46
+ raw_data = create_notification(data: { 'text' => "@trackinguser [2h]" }, date: "2012-10-28T21:06:14.801Z")
47
+
48
+ Tracking.new(raw_data).estimate.should == Estimate.new(amount: 2.0, date: Date.parse('2012-10-28'))
49
+ end
50
+
51
+ it "converts the estimate in hours when the notification contains an estimate in days" do
52
+ Tracking.new(create_notification(data: { 'text' => "@trackinguser [1.5d]" })).estimate.amount.should == 8+4
53
+ Tracking.new(create_notification(data: { 'text' => "@trackinguser [1.5g]" })).estimate.amount.should == 8+4
54
+ end
55
+
56
+ it "converts the estimate in hours when the notification contains an estimate in pomodori" do
57
+ raw_data = create_notification(data: { 'text' => "@trackinguser [10p]" })
58
+ Tracking.new(raw_data).estimate.amount.should == 5
59
+ end
60
+
61
+ it "fetch the estimate from a complex estimate message" do
62
+ raw_data = create_notification(data: { 'text' => "@maxmazza Dobbiamo ancora lavorarci.\n@trackinguser ristimo ancora [3h] per il fix" })
63
+ Tracking.new(raw_data).estimate.amount.should == 3.0
64
+ end
65
+
66
+ it "tracks the effort with the date given in the notification text, not the actual notification date" do
67
+ raw_data = create_notification( data: { 'text' => "@trackinguser 22.11.2012 [6p]" }, date: "2012-09-19T12:46:13.713Z")
68
+
69
+ tracking = Tracking.new(raw_data)
70
+
71
+ tracking.estimate.date.should == Date.parse('2012-11-22')
72
+ end
73
+
74
+ end
75
+
76
+ describe "#effort?" do
77
+ it "is false when the notification does not contain an estimate" do
78
+ Tracking.new(unrecognized_notification).effort?.should be_false
79
+ end
80
+
81
+ TIME_MEASUREMENTS.each_key do |time_measurement|
82
+ it "is true when the notification contains an estimate in #{time_measurement}" do
83
+ tracking_effort = Tracking.new(create_effort(time_measurement))
84
+
85
+ tracking_effort.effort?.should be_true
86
+ tracking_effort.estimate?.should be_false
87
+ end
88
+ end
89
+ end
90
+
91
+ describe "#effort" do
92
+
93
+ %w{pietrodibello michelepangrazzi alessandrodescovi michelevincenzi}.each do |username|
94
+ let(username.to_sym) { Member.new(username: username) }
95
+ end
96
+
97
+ before(:each) do
98
+ Trello::Member.stub(:find).and_return(Member.new(username: "any"))
99
+ end
100
+
101
+ it "is nil when the notification does not contain an estimate" do
102
+ with(unrecognized_notification) { |tracking| tracking.effort.should be_nil }
103
+ end
104
+
105
+ it "does not parse effort in minutes (e.g. +30m)" do
106
+ with_message("@trackinguser +30m") { |tracking| tracking.effort.should be_nil }
107
+ end
108
+
109
+ it "is the hour-based effort when the notification contains an effort in hours" do
110
+ Trello::Member.should_receive(:find).with("michelepangrazzi").and_return(michelepangrazzi)
111
+
112
+ raw_data = create_notification(data: { 'text' => "@trackinguser +2h" },
113
+ date: "2012-10-28T21:06:14.801Z",
114
+ member_creator: stub(username: "michelepangrazzi"))
115
+
116
+ Tracking.new(raw_data).effort.should == Effort.new(amount: 2.0, date: Date.parse('2012-10-28'), members: [michelepangrazzi])
117
+ end
118
+
119
+ it "converts the effort in hours when the notification contains an effort in days" do
120
+ with_message("@trackinguser +1.5d") { |t| t.effort.amount.should == 8+4 }
121
+ with_message("@trackinguser +1.5g") { |t| t.effort.amount.should == 8+4 }
122
+ end
123
+
124
+ it "converts the effort in hours when the notification contains an effort in pomodori" do
125
+ with_message("@trackinguser +10p") { |t| t.effort.amount.should == 5}
126
+ end
127
+
128
+ it "fetch the effort from a complex effort message" do
129
+ with_message "@trackinguser ho speso +2h e spero che stavolta possiamo rilasciarla" do |tracking|
130
+ tracking.effort.amount.should == 2.0
131
+ end
132
+ end
133
+
134
+ it "fetch the effort even when beween square brackets" do
135
+ with_message "@trackinguser [+0.5h]" do |tracking|
136
+ tracking.effort.amount.should == 0.5
137
+ end
138
+ end
139
+
140
+ it "computes the effort considering all the mentioned team mates in the message" do
141
+ with_message "@trackinguser +2h assieme a @michelepangrazzi e @alessandrodescovi" do |tracking|
142
+ tracking.effort.amount.should == 2.0 * 3
143
+ end
144
+ end
145
+
146
+ it "tracks all the team mates which spent that effort on the card" do
147
+ %w{pietrodibello michelepangrazzi alessandrodescovi}.each do |username|
148
+ Trello::Member.should_receive(:find).with(username).and_return(self.send(username))
149
+ end
150
+
151
+ notification = create_notification(data: { 'text' => "@trackinguser +2h assieme a @michelepangrazzi e @alessandrodescovi" },
152
+ member_creator: stub(username: "pietrodibello"))
153
+ with notification do |tracking|
154
+ tracking.effort.members.should == [michelepangrazzi, alessandrodescovi, pietrodibello]
155
+ end
156
+ end
157
+
158
+ it "tracks the effort only on the team members listed between round brackets" do
159
+ %w{michelevincenzi alessandrodescovi}.each do |username|
160
+ Trello::Member.should_receive(:find).with(username).and_return(self.send(username))
161
+ end
162
+
163
+ notification = create_notification(data: { 'text' => "@trackinguser +3p (@alessandrodescovi @michelevincenzi)" },
164
+ member_creator: stub(username: "pietrodibello"))
165
+
166
+ with notification do |tracking|
167
+ tracking.effort.members.should == [alessandrodescovi, michelevincenzi]
168
+ tracking.effort.amount.should == 1.5 * 2
169
+ end
170
+ end
171
+
172
+ it "does not have an effort when is an estimate" do
173
+ raw_data = create_notification(data: { 'text' => "@trackinguser stimata [6h]" })
174
+
175
+ tracking = Tracking.new(raw_data)
176
+
177
+ tracking.effort.should be_nil
178
+ end
179
+
180
+ it "tracks the effort with the date given in the notification text, not the actual notification date" do
181
+ raw_data = create_notification(data: { 'text' => "@trackinguser 22.11.2012 +6p" }, date: "2012-09-19T12:46:13.713Z")
182
+
183
+ tracking = Tracking.new(raw_data)
184
+
185
+ tracking.effort.date.should == Date.parse('2012-11-22')
186
+ end
187
+
188
+ it "tracks the effort to yesterday when the keyword 'yesterday' is present before the effort amount" do
189
+ raw_data = create_notification(data: { 'text' => "@trackinguser yesterday +6p" }, date: "2012-09-19T12:46:13.713Z")
190
+
191
+ tracking = Tracking.new(raw_data)
192
+
193
+ tracking.effort.date.should == Date.parse('2012-09-18')
194
+ end
195
+
196
+ it "tracks the effort to yesterday when the keyword 'yesterday' is present before the effort amount" do
197
+ raw_data = create_notification(data: { 'text' => "@trackinguser +6p yesterday" }, date: "2012-09-19T12:46:13.713Z")
198
+
199
+ tracking = Tracking.new(raw_data)
200
+
201
+ tracking.effort.date.should == Date.parse('2012-09-18')
202
+ end
203
+
204
+ end
205
+
206
+ private
207
+
208
+ def notification_with_message(message)
209
+ create_notification(data: { 'text' => message })
210
+ end
211
+
212
+ def create_notification(custom_params)
213
+ params = { data: { 'text' => "@trackinguser +2h" }, date: "2012-10-28T21:06:14.801Z", member_creator: stub(username: "pietrodibello") }
214
+ params.merge!(custom_params)
215
+
216
+ stub(data: params[:data], date: params[:date], member_creator: params[:member_creator]).as_null_object
217
+ end
218
+
219
+ def create_estimate(time_measurement)
220
+ create_notification(data: { 'text' => "@trackinguser [1.5#{TIME_MEASUREMENTS[time_measurement]}]" })
221
+ end
222
+
223
+ def create_effort(time_measurement)
224
+ create_notification(data: { 'text' => "@trackinguser +4.5#{TIME_MEASUREMENTS[time_measurement]}]" })
225
+ end
226
+
227
+ def with(notification)
228
+ tracking = Tracking.new(notification)
229
+ yield(tracking)
230
+ end
231
+
232
+ def with_message(notification_message, &block)
233
+ with(notification_with_message(notification_message), &block)
234
+ end
235
+
236
+ end
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+ require 'trello'
3
+
4
+ describe TrelloAuthorize do
5
+ include Trello::Authorization
6
+ include TrelloAuthorize
7
+
8
+ before(:each) do
9
+ keep_original_auth_envs
10
+ end
11
+
12
+ after(:each) do
13
+ reset_original_auth_envs
14
+ end
15
+
16
+ describe "#authorize_on_trello" do
17
+
18
+ it "creates oath credentials using auth params given as params when present as arguments, ignoring env vars or config YML vars" do
19
+ ENV["developer_public_key"] = ENV["access_token_key"] = ENV["developer_secret"] = "anything"
20
+ YAML.should_receive(:load_file).never
21
+
22
+ authorize_on_trello("developer_public_key" => "custom_dpk", "access_token_key" => "custom_atk", "developer_secret" => "custom_ds")
23
+
24
+ Trello::Authorization::OAuthPolicy.consumer_credential.key.should == "custom_dpk"
25
+ Trello::Authorization::OAuthPolicy.consumer_credential.secret.should == "custom_ds"
26
+ Trello::Authorization::OAuthPolicy.token.key.should == "custom_atk"
27
+ end
28
+
29
+ it "creates oath credentials using auth params taken from env variables when auth params are not given as arguments" do
30
+ ENV["developer_public_key"] = "my_dpk"
31
+ ENV["access_token_key"] = "my_atk"
32
+ ENV["developer_secret"] = "my_ds"
33
+
34
+ YAML.should_receive(:load_file).never
35
+
36
+ authorize_on_trello("any" => "thing")
37
+
38
+ Trello::Authorization::OAuthPolicy.consumer_credential.key.should == "my_dpk"
39
+ Trello::Authorization::OAuthPolicy.consumer_credential.secret.should == "my_ds"
40
+ Trello::Authorization::OAuthPolicy.token.key.should == "my_atk"
41
+ end
42
+
43
+ it "creates oath credentials using auth params from config file when auth env variables are not set" do
44
+ ENV["developer_public_key"] = ENV["access_token_key"] = ENV["developer_secret"] = nil
45
+
46
+ config_hash = {"trello" => { "developer_public_key" => "any_dpk", "access_token_key" => "any_atk", "developer_secret" => "any_ds"}}
47
+ YAML.should_receive(:load_file).with("config/config.yml").and_return(config_hash)
48
+
49
+ authorize_on_trello("any" => "thing")
50
+
51
+ Trello::Authorization::OAuthPolicy.consumer_credential.key.should == "any_dpk"
52
+ Trello::Authorization::OAuthPolicy.consumer_credential.secret.should == "any_ds"
53
+ Trello::Authorization::OAuthPolicy.token.key.should == "any_atk"
54
+ end
55
+
56
+ end
57
+
58
+ private
59
+
60
+ def keep_original_auth_envs
61
+ @original_developer_public_key = ENV["developer_public_key"]
62
+ @original_access_token_key = ENV["access_token_key"]
63
+ @original_developer_secret = ENV["developer_secret"]
64
+ end
65
+
66
+ def reset_original_auth_envs
67
+ ENV["developer_public_key"] = @original_developer_public_key
68
+ ENV["access_token_key"] = @original_access_token_key
69
+ ENV["developer_secret"] = @original_developer_secre
70
+ end
71
+ end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+ require 'trello'
3
+
4
+ describe TrelloConfiguration do
5
+ include TrelloConfiguration
6
+
7
+ describe "#authorization_params_from_config_file" do
8
+ it "loads the default trello auth params from config yml" do
9
+ config_hash = {"trello" => { "developer_public_key" => "any_dpk", "access_token_key" => "any_atk", "developer_secret" => "any_ds"} }
10
+ YAML.should_receive(:load_file).with("config/config.yml").and_return(config_hash)
11
+
12
+ authorization_params_from_config_file["developer_public_key"].should == "any_dpk"
13
+ authorization_params_from_config_file["access_token_key"].should == "any_atk"
14
+ authorization_params_from_config_file["developer_secret"].should == "any_ds"
15
+ end
16
+ end
17
+
18
+ describe "#tracker_username" do
19
+ before(:each) do
20
+ @original = ENV["tracker_username"]
21
+ end
22
+
23
+ after(:each) do
24
+ ENV["tracker_username"] = @original
25
+ end
26
+
27
+ it "searches for the trello tracker username first from an env var" do
28
+ ENV["tracker_username"] = "my_tracker"
29
+ YAML.should_receive(:load_file).never
30
+
31
+ tracker_username.should == "my_tracker"
32
+ end
33
+ it "searches for the trello tracker username in the config yml file if the env var is not set" do
34
+ ENV["tracker_username"] = nil
35
+ config_hash = {"tracker_username" => "my_trello_tracker" }
36
+ YAML.should_receive(:load_file).with("config/config.yml").and_return(config_hash)
37
+
38
+ tracker_username.should == "my_trello_tracker"
39
+ end
40
+
41
+ end
42
+
43
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/trello_effort_tracker/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "trello_effort_tracker"
6
+ gem.version = TrelloEffortTracker::VERSION
7
+ gem.description = "A tool to extract estimates and efforts from Trello"
8
+ gem.summary = "You notify all the estimates and efforts of your Trello cards. This tool will extract and store these estimates and actual efforts to let you extract useful key metrics (e.g. estimate errors)"
9
+ gem.authors = ['Pietro Di Bello']
10
+ gem.email = 'pierodibello@gmail.com'
11
+ gem.homepage = 'http://xplayer.wordpress.com'
12
+ gem.date = Time.now.strftime "%Y-%m-%d"
13
+ gem.require_paths = ["lib"]
14
+ gem.files = `git ls-files`.split("\n")
15
+ gem.test_files = `git ls-files -- {spec}/*`.split("\n")
16
+ gem.extra_rdoc_files = ["README.md"]
17
+ gem.rubygems_version = %q{1.8.24}
18
+ gem.required_rubygems_version = ">= 1.3.6"
19
+ end