tracco 0.0.14 → 0.0.15
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.
- 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
|