tracco 0.0.14 → 0.0.15
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +16 -0
- data/Gemfile.lock +1 -1
- data/README.md +4 -4
- data/lib/patches/trello/card.rb +3 -2
- data/lib/patches/trello/member.rb +4 -2
- data/lib/tasks/tasks.rake +2 -2
- data/lib/tracco/google_docs_exporter.rb +50 -47
- data/lib/tracco/models/effort.rb +40 -0
- data/lib/tracco/models/estimate.rb +29 -0
- data/lib/tracco/models/member.rb +64 -0
- data/lib/tracco/models/tracked_card.rb +148 -0
- data/lib/tracco/tracking/base.rb +68 -65
- data/lib/tracco/tracking/card_done_tracking.rb +9 -6
- data/lib/tracco/tracking/effort_tracking.rb +32 -29
- data/lib/tracco/tracking/estimate_tracking.rb +16 -13
- data/lib/tracco/tracking/factory.rb +18 -16
- data/lib/tracco/tracking/invalid_tracking.rb +15 -13
- data/lib/tracco/trello_tracker.rb +34 -30
- data/lib/tracco/version.rb +2 -2
- data/lib/tracco.rb +4 -4
- data/spec/factories/effort_factory.rb +2 -2
- data/spec/factories/estimate_factory.rb +1 -1
- data/spec/factories/tracked_card_factory.rb +1 -1
- data/spec/integration/trello_tracker_spec.rb +49 -47
- data/spec/models/effort_spec.rb +61 -0
- data/spec/models/estimate_spec.rb +40 -0
- data/spec/models/member_spec.rb +83 -0
- data/spec/models/tracked_card_spec.rb +467 -0
- data/spec/support/spec_helper_methods.rb +7 -1
- data/spec/tracking/card_done_tracking_spec.rb +11 -9
- data/spec/tracking/effort_tracking_spec.rb +77 -75
- data/spec/tracking/estimate_tracking_spec.rb +30 -28
- data/spec/tracking/factory_spec.rb +39 -0
- data/spec/trello_tracker_spec.rb +20 -18
- data/tracco.gemspec +1 -1
- metadata +12 -12
- data/lib/tracco/effort.rb +0 -37
- data/lib/tracco/estimate.rb +0 -26
- data/lib/tracco/member.rb +0 -61
- data/lib/tracco/tracked_card.rb +0 -145
- data/spec/effort_spec.rb +0 -59
- data/spec/estimate_spec.rb +0 -38
- data/spec/member_spec.rb +0 -81
- data/spec/tracked_card_spec.rb +0 -465
- data/spec/tracking_factory_spec.rb +0 -42
@@ -1,42 +1,45 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
1
|
+
module Tracco
|
2
|
+
module Tracking
|
3
|
+
class EffortTracking
|
4
|
+
include Base
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
def add_to(card)
|
7
|
+
card.efforts << effort unless card.contains_effort?(effort)
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
def effort
|
11
|
+
@effort ||= Effort.new(amount: total_effort_from(raw_effort), date: date, members: effort_members, tracking_notification_id: tracking_notification.id)
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
+
private
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
def total_effort_from(raw_effort)
|
17
|
+
effort_amount = convert_to_hours(raw_effort)
|
18
|
+
total_effort = effort_amount * effort_members.size
|
19
|
+
end
|
19
20
|
|
20
|
-
|
21
|
-
|
22
|
-
|
21
|
+
def raw_effort
|
22
|
+
extract_match_from_raw_tracking(/\+#{DURATION_REGEXP}/)
|
23
|
+
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
|
25
|
+
def effort_members
|
26
|
+
@effort_members ||= members_involved_in_the_effort.map do |username|
|
27
|
+
Member.build_from(Trello::Member.find(username))
|
28
|
+
end
|
27
29
|
end
|
28
|
-
end
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
def members_involved_in_the_effort
|
32
|
+
members_involved_in_the_effort = raw_tracking.scan(/@(\w+)/).flatten
|
33
|
+
members_involved_in_the_effort << notifier.username unless should_count_only_listed_members?
|
33
34
|
|
34
|
-
|
35
|
-
|
35
|
+
members_involved_in_the_effort
|
36
|
+
end
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
38
|
+
def should_count_only_listed_members?
|
39
|
+
raw_tracking =~ /\((@\w+\W*\s*)+\)/
|
40
|
+
end
|
40
41
|
|
42
|
+
end
|
41
43
|
end
|
44
|
+
|
42
45
|
end
|
@@ -1,20 +1,23 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
1
|
+
module Tracco
|
2
|
+
module Tracking
|
3
|
+
class EstimateTracking
|
4
|
+
include Base
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
6
|
+
def estimate
|
7
|
+
@estimate ||= Estimate.new(amount: convert_to_hours(raw_estimate), date: date, tracking_notification_id: tracking_notification.id)
|
8
|
+
end
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
10
|
+
def add_to(card)
|
11
|
+
card.estimates << estimate unless card.contains_estimate?(estimate)
|
12
|
+
end
|
12
13
|
|
13
|
-
|
14
|
+
private
|
14
15
|
|
15
|
-
|
16
|
-
|
17
|
-
|
16
|
+
def raw_estimate
|
17
|
+
extract_match_from_raw_tracking(/\[#{DURATION_REGEXP}\]/)
|
18
|
+
end
|
18
19
|
|
20
|
+
end
|
19
21
|
end
|
22
|
+
|
20
23
|
end
|
@@ -1,26 +1,28 @@
|
|
1
|
-
module
|
2
|
-
|
1
|
+
module Tracco
|
2
|
+
module Tracking
|
3
|
+
class Factory
|
3
4
|
|
4
|
-
|
5
|
+
DURATION_REGEXP = '(\d+\.?\d*[phdg])'
|
5
6
|
|
6
|
-
|
7
|
+
@match_pairs = {}
|
7
8
|
|
8
|
-
|
9
|
-
|
9
|
+
def self.build_from(tracking_notification)
|
10
|
+
matching_pair = @match_pairs.find { |regexp, tracking_class| tracking_notification.data['text'] =~ regexp }
|
10
11
|
|
11
|
-
|
12
|
-
|
13
|
-
|
12
|
+
tracking_class = matching_pair ? matching_pair.last : Tracking::InvalidTracking
|
13
|
+
tracking_class.new(tracking_notification)
|
14
|
+
end
|
14
15
|
|
15
|
-
|
16
|
+
private
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
def self.match(match_pair)
|
19
|
+
@match_pairs.merge!(match_pair)
|
20
|
+
end
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
22
|
+
match /\[#{DURATION_REGEXP}\]/ => Tracking::EstimateTracking
|
23
|
+
match /\+#{DURATION_REGEXP}/ => Tracking::EffortTracking
|
24
|
+
match /DONE/ => Tracking::CardDoneTracking
|
24
25
|
|
26
|
+
end
|
25
27
|
end
|
26
28
|
end
|
@@ -1,19 +1,21 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
1
|
+
module Tracco
|
2
|
+
module Tracking
|
3
|
+
class InvalidTracking
|
4
|
+
include Base
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
def add_to(card)
|
7
|
+
# do nothing
|
8
|
+
Trello.logger.warn "Ignoring tracking notification: '#{raw_text}'"
|
9
|
+
end
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
11
|
+
def estimate
|
12
|
+
nil
|
13
|
+
end
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
15
|
+
def effort
|
16
|
+
nil
|
17
|
+
end
|
17
18
|
|
19
|
+
end
|
18
20
|
end
|
19
21
|
end
|
@@ -1,44 +1,48 @@
|
|
1
|
-
|
2
|
-
include TrelloAuthorize
|
3
|
-
include Trello
|
1
|
+
module Tracco
|
4
2
|
|
5
|
-
|
3
|
+
class TrelloTracker
|
4
|
+
include TrelloAuthorize
|
5
|
+
include Trello
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
7
|
+
trap("SIGINT") { exit! }
|
8
|
+
|
9
|
+
def initialize(custom_config_params = {})
|
10
|
+
authorize_on_trello(custom_config_params)
|
11
|
+
tracker_username(custom_config_params[:tracker_username])
|
12
|
+
end
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
+
def track(starting_date=Date.today)
|
15
|
+
tracking_notifications = tracker.tracking_notifications_since(starting_date)
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
+
oldest, latest = boundary_dates_in(tracking_notifications)
|
18
|
+
Trello.logger.info "Processing #{tracking_notifications.size} tracking events (from #{oldest} to #{latest}) starting from #{starting_date}..."
|
17
19
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
20
|
+
tracking_notifications.each do |tracking_notification|
|
21
|
+
tracking = Tracking::Factory.build_from(tracking_notification)
|
22
|
+
begin
|
23
|
+
tracked_card = TrackedCard.update_or_create_with(tracking_notification.card)
|
24
|
+
tracked_card.add!(tracking)
|
25
|
+
Trello.logger.info tracking
|
24
26
|
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
rescue StandardError => e
|
28
|
+
Trello.logger.warn "skipping tracking: #{e.message}".color(:magenta)
|
29
|
+
Trello.logger.debug "#{e.backtrace}"
|
30
|
+
end
|
28
31
|
end
|
32
|
+
Trello.logger.info "Done tracking cards!".color(:green)
|
29
33
|
end
|
30
|
-
Trello.logger.info "Done tracking cards!".color(:green)
|
31
|
-
end
|
32
34
|
|
33
|
-
|
35
|
+
private
|
34
36
|
|
35
|
-
|
36
|
-
|
37
|
-
|
37
|
+
def tracker
|
38
|
+
@tracker ||= Trello::Member.find(tracker_username)
|
39
|
+
end
|
40
|
+
|
41
|
+
def boundary_dates_in(tracking_notifications)
|
42
|
+
dates = tracking_notifications.map { |each_tracking_notification| Chronic.parse(each_tracking_notification.date) }
|
43
|
+
[dates.min, dates.max]
|
44
|
+
end
|
38
45
|
|
39
|
-
def boundary_dates_in(notifications)
|
40
|
-
dates = notifications.map { |each_notification| Chronic.parse(each_notification.date) }
|
41
|
-
[dates.min, dates.max]
|
42
46
|
end
|
43
47
|
|
44
48
|
end
|
data/lib/tracco/version.rb
CHANGED
@@ -1,3 +1,3 @@
|
|
1
|
-
|
2
|
-
VERSION = '0.0.
|
1
|
+
module Tracco
|
2
|
+
VERSION = '0.0.15'
|
3
3
|
end
|
data/lib/tracco.rb
CHANGED
@@ -9,10 +9,10 @@ require 'forwardable'
|
|
9
9
|
require 'tracco/mongoid_helper'
|
10
10
|
require 'tracco/trello_configuration'
|
11
11
|
require 'tracco/trello_authorize'
|
12
|
-
require 'tracco/tracked_card'
|
13
|
-
require 'tracco/member'
|
14
|
-
require 'tracco/estimate'
|
15
|
-
require 'tracco/effort'
|
12
|
+
require 'tracco/models/tracked_card'
|
13
|
+
require 'tracco/models/member'
|
14
|
+
require 'tracco/models/estimate'
|
15
|
+
require 'tracco/models/effort'
|
16
16
|
require 'tracco/tracking/base'
|
17
17
|
require 'tracco/tracking/estimate_tracking'
|
18
18
|
require 'tracco/tracking/effort_tracking'
|
@@ -1,9 +1,9 @@
|
|
1
1
|
FactoryGirl.define do
|
2
2
|
|
3
|
-
factory :effort do
|
3
|
+
factory :effort, :class => Tracco::Effort do
|
4
4
|
amount 4
|
5
5
|
date Date.today
|
6
|
-
members [Member.new(username: "any_name")]
|
6
|
+
members [Tracco::Member.new(username: "any_name")]
|
7
7
|
sequence(:tracking_notification_id, 1000)
|
8
8
|
muted false
|
9
9
|
end
|
@@ -1,66 +1,68 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
require 'ostruct'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
module Tracco
|
5
|
+
describe TrelloTracker do
|
6
|
+
# This integration test works on a real Trello board created just for this purpose
|
7
|
+
# (see https://trello.com/board/testingboard/50ff225c7162123e3600074f)
|
8
|
+
# The board has some cards in todo, one card in progress and one done
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
TODO_CARD_ID = "51062b71df2bfec47b0039fb"
|
11
|
+
IN_PROGRESS_CARD_ID = "51062b99d81a343121004046"
|
12
|
+
DONE_CARD_ID = "51062b936d2deed22100157e"
|
13
|
+
ANOTHER_DONE_CARD_ID = "510c46d7c7bc9ac6020007ab"
|
13
14
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
15
|
+
let(:config) {
|
16
|
+
# auth params for trackinguser_for_test/testinguser!
|
17
|
+
OpenStruct.new(tracker: "trackinguser_for_test",
|
18
|
+
dev_key: "ef7c400e711057d7ba5e00be20139a33",
|
19
|
+
token: "9047d8fdbfdc960d41910673e300516cc8630dd4967e9b418fc27e410516362e")
|
20
|
+
}
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
it "tracks some estimates and efforts", :needs_valid_configuration => true do
|
23
|
+
without_logging do
|
24
|
+
tracker = TrelloTracker.new(tracker_username: config.tracker, developer_public_key: config.dev_key, access_token_key: config.token)
|
25
|
+
tracker.track(DateTime.parse("2013-01-28"))
|
26
|
+
end
|
26
27
|
|
27
|
-
|
28
|
-
|
28
|
+
# a card to do
|
29
|
+
todo_card = TrackedCard.find_by_trello_id(TODO_CARD_ID)
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
31
|
+
todo_card.estimates.should have(1).estimate
|
32
|
+
todo_card.estimates.first.amount.should == 4
|
33
|
+
todo_card.should_not be_done
|
33
34
|
|
34
|
-
|
35
|
-
|
35
|
+
# a card in progress
|
36
|
+
in_progress_card = TrackedCard.find_by_trello_id(IN_PROGRESS_CARD_ID)
|
36
37
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
38
|
+
in_progress_card.estimates.should have(1).estimate
|
39
|
+
in_progress_card.estimates.should have(1).effort
|
40
|
+
in_progress_card.estimates.first.amount.should == 5
|
41
|
+
in_progress_card.efforts.first.amount.should == 1
|
42
|
+
in_progress_card.should_not be_done
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
# a done card
|
45
|
+
done_card = TrackedCard.find_by_trello_id(DONE_CARD_ID)
|
46
|
+
done_card.total_effort.should == 2
|
47
|
+
done_card.should be_done
|
47
48
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
49
|
+
# another done card (this time for the DONE column)
|
50
|
+
another_done_card = TrackedCard.find_by_trello_id(ANOTHER_DONE_CARD_ID)
|
51
|
+
another_done_card.should be_done
|
52
|
+
end
|
52
53
|
|
53
54
|
|
54
|
-
|
55
|
+
private
|
55
56
|
|
56
|
-
|
57
|
-
|
57
|
+
def without_logging(&block)
|
58
|
+
original_error_level = Trello.logger.level
|
58
59
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
60
|
+
begin
|
61
|
+
Trello.logger.level = Logger::WARN
|
62
|
+
block.call unless block.nil?
|
63
|
+
ensure
|
64
|
+
Trello.logger.level = original_error_level
|
65
|
+
end
|
64
66
|
end
|
65
67
|
end
|
66
68
|
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'mongoid-rspec'
|
3
|
+
|
4
|
+
module Tracco
|
5
|
+
describe Effort do
|
6
|
+
|
7
|
+
it { should have_fields(:amount, :date, :muted, :tracking_notification_id) }
|
8
|
+
it { should be_embedded_in(:tracked_card) }
|
9
|
+
it { should embed_many(:members) }
|
10
|
+
|
11
|
+
describe "validation" do
|
12
|
+
it { should validate_presence_of(:amount) }
|
13
|
+
it { should validate_presence_of(:date) }
|
14
|
+
it { should validate_presence_of(:members) }
|
15
|
+
end
|
16
|
+
|
17
|
+
%w{piero tommaso tom ugo}.each do |username|
|
18
|
+
let(username.to_sym) { Member.new(username: username) }
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#amount_per_member" do
|
22
|
+
it "counts the amount spent per single member" do
|
23
|
+
effort = Effort.new(amount: 6, members: [piero, tommaso], date: Date.parse("2012-11-09"), )
|
24
|
+
effort.amount_per_member.should == 3
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "equality" do
|
29
|
+
it "is equal to another effort with same amount, date and members" do
|
30
|
+
effort = Effort.new(amount: 3, date: Date.parse("2012-11-09"), members: [piero, tommaso])
|
31
|
+
same_effort = Effort.new(amount: 3, date: Date.parse("2012-11-09"), members: [piero, tommaso])
|
32
|
+
yet_same_effort = Effort.new(amount: 3, date: Date.parse("2012-11-09"), members: [tommaso, piero])
|
33
|
+
|
34
|
+
effort.should == same_effort
|
35
|
+
effort.should == yet_same_effort
|
36
|
+
end
|
37
|
+
|
38
|
+
it "is not equal when amount differs" do
|
39
|
+
effort = Effort.new(amount: 3, date: Date.today, members: [tom, ugo])
|
40
|
+
another_effort = Effort.new(amount: 1, date: Date.today, members: [tom, ugo])
|
41
|
+
|
42
|
+
effort.should_not == another_effort
|
43
|
+
end
|
44
|
+
|
45
|
+
it "is not equal when date differs" do
|
46
|
+
effort = Effort.new(amount: 3, date: Date.parse("2012-11-09"), members: [tom, ugo])
|
47
|
+
another_effort = Effort.new(amount: 3, date: Date.parse("2011-10-08"), members: [tom, ugo])
|
48
|
+
|
49
|
+
effort.should_not == another_effort
|
50
|
+
end
|
51
|
+
|
52
|
+
it "is not equal when members differ" do
|
53
|
+
effort = Effort.new(amount: 3, date: Date.today, members: [tom, ugo])
|
54
|
+
another_effort = Effort.new(amount: 3, date: Date.today, members: [piero, ugo])
|
55
|
+
|
56
|
+
effort.should_not == another_effort
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'mongoid-rspec'
|
3
|
+
|
4
|
+
module Tracco
|
5
|
+
describe Estimate do
|
6
|
+
|
7
|
+
it { should have_fields(:amount, :date) }
|
8
|
+
it { should be_embedded_in(:tracked_card) }
|
9
|
+
|
10
|
+
describe "validation" do
|
11
|
+
it { should validate_presence_of(:amount) }
|
12
|
+
it { should validate_presence_of(:date) }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "equality" do
|
16
|
+
|
17
|
+
it "is equal to another estimate with same amount and date" do
|
18
|
+
estimate = Estimate.new(amount: 3, date: Date.parse("2012-11-09"))
|
19
|
+
same_estimate = Estimate.new(amount: 3, date: Date.parse("2012-11-09"))
|
20
|
+
|
21
|
+
estimate.should == same_estimate
|
22
|
+
end
|
23
|
+
|
24
|
+
it "is not equal when amount differs" do
|
25
|
+
estimate = Estimate.new(amount: 3, date: Date.today)
|
26
|
+
another_estimate = Estimate.new(amount: 1, date: Date.today)
|
27
|
+
|
28
|
+
estimate.should_not == another_estimate
|
29
|
+
end
|
30
|
+
|
31
|
+
it "is not equal when date differs" do
|
32
|
+
estimate = Estimate.new(amount: 3, date: Date.parse("2012-11-09"))
|
33
|
+
another_estimate = Estimate.new(amount: 3, date: Date.parse("2011-10-08"))
|
34
|
+
|
35
|
+
estimate.should_not == another_estimate
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'mongoid-rspec'
|
3
|
+
|
4
|
+
module Tracco
|
5
|
+
describe Member do
|
6
|
+
|
7
|
+
it { should have_fields(:trello_id, :username, :full_name, :avatar_id, :bio, :url) }
|
8
|
+
it { should be_embedded_in(:effort) }
|
9
|
+
|
10
|
+
describe "validation" do
|
11
|
+
it { should validate_presence_of(:username) }
|
12
|
+
end
|
13
|
+
|
14
|
+
describe "equality" do
|
15
|
+
it "is equal to another member with the same username" do
|
16
|
+
member = Member.new(username: "piero")
|
17
|
+
same_member = Member.new(username: "piero")
|
18
|
+
different_member = Member.new(username: "tommaso")
|
19
|
+
|
20
|
+
member.should == same_member
|
21
|
+
member.should_not == different_member
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe ".build_from" do
|
26
|
+
it "builds a Member from a Trello Member" do
|
27
|
+
member = Member.build_from(Trello::Member.new("username" => "piero"))
|
28
|
+
|
29
|
+
member.username.should == "piero"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "takes the Trello Member id and set it as trello_id" do
|
33
|
+
member = Member.build_from(Trello::Member.new("username" => "piero", "id" => "1234567abc"))
|
34
|
+
|
35
|
+
member.id.should_not == "1234567abc"
|
36
|
+
member.trello_id.should == "1234567abc"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
describe "#effort_spent" do
|
41
|
+
%w{piero tommaso}.each do |username|
|
42
|
+
let(username.to_sym) { Member.new(username: username) }
|
43
|
+
end
|
44
|
+
|
45
|
+
let(:card) { TrackedCard.create(name: "any", short_id: 1234, trello_id: "123123") }
|
46
|
+
let(:another_card) { TrackedCard.create(name: "any_other", short_id: 1235, trello_id: "123125") }
|
47
|
+
|
48
|
+
it "is zero when the member did not spent effort at all" do
|
49
|
+
piero.effort_spent.should == 0
|
50
|
+
end
|
51
|
+
|
52
|
+
it "counts the effort spent on a card" do
|
53
|
+
card.efforts << Effort.new(amount: 4, date: Date.today, members: [piero, tommaso])
|
54
|
+
card.efforts << Effort.new(amount: 5, date: Date.today, members: [tommaso])
|
55
|
+
|
56
|
+
piero.effort_spent.should == 4 / 2
|
57
|
+
end
|
58
|
+
|
59
|
+
it "counts the effort spent on several cards" do
|
60
|
+
card.efforts << Effort.new(amount: 4, date: Date.today, members: [piero, tommaso])
|
61
|
+
another_card.efforts << Effort.new(amount: 5, date: Date.today, members: [piero])
|
62
|
+
|
63
|
+
piero.effort_spent.should == 2 + 5
|
64
|
+
end
|
65
|
+
|
66
|
+
it "counts the effort spent on a card from a given date" do
|
67
|
+
card.efforts << Effort.new(amount: 4, date: Date.yesterday, members: [piero])
|
68
|
+
card.efforts << Effort.new(amount: 5, date: Date.today, members: [piero])
|
69
|
+
|
70
|
+
piero.effort_spent(Date.today).should == 5
|
71
|
+
piero.effort_spent_since(Date.today).should == 5
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "#avatar_url" do
|
77
|
+
it "points to the avatar thumbnail image" do
|
78
|
+
member = Member.new(avatar_id: "123xyz")
|
79
|
+
member.avatar_url.should == "https://trello-avatars.s3.amazonaws.com/123xyz/30.png"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|